Download the PHP package john-wink/telli-laravel-wrapper without Composer

On this page you can find all versions of the php package john-wink/telli-laravel-wrapper. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package telli-laravel-wrapper

Telli Laravel Wrapper

Latest Version on Packagist GitHub Tests Action Status Total Downloads

A Laravel wrapper for the telli API - AI phone call agents. Covers the v2 contacts/properties/agents API and the v1 calls, dialer and webhook surface. Fully typed DTOs via spatie/laravel-data, a typed exception per documented API error code, cursor pagination as lazy collections, and an idempotent contact create.

Requirements

Installation

composer require john-wink/telli-laravel-wrapper

Publish the config file (optional):

php artisan vendor:publish --tag="telli-config"

Publish the translations (optional, ships with en and de):

php artisan vendor:publish --tag="telli-translations"

Set your API key in .env:

TELLI_API_KEY=your-api-key

Usage

Contacts

use JohnWink\Telli\Facades\Telli;
use JohnWink\Telli\Data\CreateContactData;
use JohnWink\Telli\Data\UpdateContactData;
use JohnWink\Telli\Data\ContactPropertyInputData;
use Spatie\LaravelData\DataCollection;

$contact = Telli::contacts()->create(new CreateContactData(
    firstName: 'Max',
    lastName: 'Mustermann',
    phoneNumber: '+4915112345678',
    externalId: 'lead-4711',
    properties: new DataCollection(ContactPropertyInputData::class, [
        new ContactPropertyInputData(key: 'lead_score', value: 87),
    ]),
));

$page = Telli::contacts()->list(limit: 100);          // one page + pageInfo/meta
Telli::contacts()->all()->each(fn ($contact) => ...); // lazy, follows the cursor

$contact = Telli::contacts()->get($id);
$contact = Telli::contacts()->getByExternalId('lead-4711');
$contact = Telli::contacts()->update($id, new UpdateContactData(email: '[email protected]'));
Telli::contacts()->delete($id);

Replace semantics: Telli::contacts()->replace($id, $data) issues a PUT. Optional fields you omit are reset to null (respectively [] for properties) on the server - unlike update(), which only touches the fields you send.

Idempotent create: when externalId is set and the API answers with a 5xx or the connection drops, the wrapper looks the contact up by external ID before retrying - you never create duplicates. Without an externalId there is nothing to check against, so a failed create is NOT retried; set an externalId whenever you can.

Contact properties

use JohnWink\Telli\Data\CreateContactPropertyData;
use JohnWink\Telli\Data\UpdateContactPropertyData;
use JohnWink\Telli\Enums\PropertyDataType;

$properties = Telli::contactProperties()->list();
$property = Telli::contactProperties()->create(new CreateContactPropertyData(
    key: 'lead_score',
    dataType: PropertyDataType::Number,
    label: 'Lead Score',
));
$property = Telli::contactProperties()->get('lead_score');
$property = Telli::contactProperties()->update('lead_score', new UpdateContactPropertyData(label: 'Score'));

Agents & account health

$agents = Telli::agents()->all();          // lazy collection over all pages
$agent = Telli::agents()->get($agentId);
$health = Telli::account()->health();      // AccountHealthStatus::Operational|Degraded

Calls (v1 API)

telli's call endpoints live on the v1 API (v2 does not cover calls yet); the wrapper maps them to the same camelCase PHP API:

use JohnWink\Telli\Data\Calls\ScheduleCallData;
use JohnWink\Telli\Data\Calls\ScheduleData;

$result = Telli::calls()->schedule(new ScheduleCallData(
    contactId: $contact->id,
    agentId: $agentId,
));                                            // respects the dialer window

Telli::calls()->schedule(new ScheduleCallData(
    contactId: $contact->id,
    agentId: $agentId,
    schedule: ScheduleData::for(now()->addHours(2)),
));                                            // scheduled for a specific time

$call = Telli::calls()->get($callId);          // transcript, analysis, booked_slot_for, recording
$page = Telli::calls()->list(contactId: $contact->id);

Telli::calls()->initiate(...);                 // exists, but telli recommends schedule() -
                                               // initiate() calls even outside business hours

Telli::dialer()->remove($contactId) takes a contact out of the auto-dialer loop; Telli::phoneNumbers() manages SIP numbers. A 402 response (insufficient funds) raises a typed PaymentRequiredException.

Telli::account()->verifyApiKey() returns whether the configured key is valid - handy for settings screens.

Webhooks

telli signs webhooks with Svix. Verify and parse them without extra dependencies:

use JohnWink\Telli\Facades\Telli;

Telli::webhooks()->verify(
    payload: $request->getContent(),
    svixId: $request->header('svix-id'),
    svixTimestamp: $request->header('svix-timestamp'),
    svixSignature: $request->header('svix-signature'),
    secret: $connection->webhook_secret,
);                                             // throws TelliWebhookSignatureException on mismatch

$event = Telli::webhooks()->parse($request->json()->all());

if ($call = $event->call()) {                  // call_ended events
    $call->transcript; $call->bookedSlotFor; $call->recordingUrl;
}

Multi-tenant / per-team API keys

The config key is just the default account. Scope any call to a different telli account at runtime - withApiKey() returns a NEW client and never mutates the shared singleton, so there is no key bleed between requests, queued jobs or Octane workers:

Telli::withApiKey($team->telli_api_key)->contacts()->create($data);

Error handling

Every documented telli error code maps to its own exception with typed fields, all extending TelliRequestException (which extends TelliException):

use JohnWink\Telli\Exceptions\ContactNotFoundException;
use JohnWink\Telli\Exceptions\TelliValidationException;
use JohnWink\Telli\Exceptions\TelliException;

try {
    Telli::contacts()->get($id);
} catch (ContactNotFoundException $exception) {
    $exception->contactId;      // typed payload from the API
} catch (TelliValidationException $exception) {
    $exception->issues;         // list of ValidationIssueData (code, message, path)
} catch (TelliException $exception) {
    // configuration, connection or any other API error
}

Exception messages are translated (en, de); the raw API message stays available via $exception->apiMessage, the raw code via $exception->rawCode.

Retries

429 responses are retried for every request; connection errors and 5xx responses are retried for non-POST requests only — a blind POST retry could create duplicates. Failed POST creates recover through the verify-then-retry mechanism instead (see "Idempotent create" above) when a natural key (externalId / property key) is present. The backoff is configurable (config/telli.php); a Retry-After header on 429 responses takes precedence.

Testing your integration

The wrapper uses Laravel's HTTP client, so Http::fake() works out of the box:

Http::fake(['api.telli.com/*' => Http::response([...])]);

Or swap the whole client with a mock:

use JohnWink\Telli\Facades\Telli;

Telli::swap($mock);

Changelog

See CHANGELOG.

License

MIT, see LICENSE.


All versions of telli-laravel-wrapper with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
illuminate/contracts Version ^12.0
illuminate/http Version ^12.0
illuminate/support Version ^12.0
nesbot/carbon Version ^3.0
spatie/laravel-data Version ^4.19
spatie/laravel-package-tools Version ^1.16
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package john-wink/telli-laravel-wrapper contains the following files

Loading the files please wait ...