Search by

shannonllc / avacast

aruimiura

PHP SDK for avacast realtime avatars: create sessions, make the avatar speak and read usage from your server.

v0.1.0 2026-10-17 11:03 UTC

This package is auto-updated.

Last update: 2026-10-17 11:05:06 UTC


README

PHP SDK for avacast realtime avatars: create sessions, make the avatar speak and read usage from your server.

  • PHP 8.1+ with ext-curl. No other dependencies.
  • Server-side only. Show the avatar in the browser with the browser SDK (avacast/web from the Node.js SDK, or https://avacast.jp/sdk/v1.js), using the session's client_token and webrtc values.

Install

composer require shannonllc/avacast

Quick start

use Avacast\Client;

$avacast = new Client('sk_live_...'); // or set AVACAST_API_KEY

$avatars = $avacast->avatars->list()['data'];
$session = $avacast->sessions->create([
    'avatar_id' => $avatars[0]['id'],
    'voice' => ['language' => 'ja', 'voice_id' => 'female-30s-clear'],
]);
// Give only these to the browser. Never ship the API key to a browser.
echo json_encode(['client_token' => $session['client_token'], 'webrtc' => $session['webrtc']]);

After the browser has connected (session.ready):

$avacast->sessions->speak($sessionId, 'ご相談ありがとうございます。');
$avacast->sessions->speak($sessionId, 'ご用件をお聞かせください。'); // no need to wait: lines are queued

$avacast->sessions->interrupt($sessionId); // the user started talking
$avacast->sessions->end($sessionId);       // billing stops when the session closes

Methods

Params and responses are arrays with the API's field names (docs).

Method API
sessions->create(['avatar_id' => …, 'voice' => […], 'idle_timeout_seconds' => …, 'metadata' => […]]) POST /v1/sessions
sessions->speak($sessionId, $text) POST /v1/sessions/:id/speak
sessions->interrupt($sessionId) POST /v1/sessions/:id/interrupt
sessions->get($sessionId) GET /v1/sessions/:id
sessions->end($sessionId) DELETE /v1/sessions/:id
avatars->list() GET /v1/avatars
usage->get() GET /v1/usage (this month)
usage->range(['from' => …, 'to' => …, 'group_by' => 'metadata.<key>']) GET /v1/usage?from=&to=&group_by=
status() GET /v1/status

Every method takes options last: ['timeout' => seconds, 'max_retries' => n], and 'idempotency_key' => … for create and speak.

Avacast\Voices::IDS (female-standard, female-30s-clear, … male-60s-deep) and Avacast\Voices::LANGUAGES (ja, en, …) are the values for voice. Without voice_id, the session uses the avatar's voice.

$avacast = new Client(getenv('AVACAST_API_KEY'), [
    'timeout' => 30,    // seconds per attempt (default)
    'max_retries' => 2, // retries after the first attempt (default)
]);

Usage

$u = $avacast->usage->range([
    'from' => new DateTimeImmutable('2026-10-01T00:00:00Z'),
    'to' => new DateTimeImmutable('2026-11-01T00:00:00Z'),
    'group_by' => 'metadata.tenant', // sessions created with 'metadata' => ['tenant' => '…']
]);
foreach ($u['data'] as $row) {
    echo $row['key'], ' ', $row['connected_seconds'], "\n";
}

You are billed for the time a session is open (connected_seconds).

Errors

use Avacast\Exception\ConflictException;
use Avacast\Exception\RateLimitException;

try {
    $avacast->sessions->speak($sessionId, $text);
} catch (ConflictException $e) {
    if ($e->errorCode === 'session_not_connected') {
        // wait for session.ready in the browser
    }
} catch (RateLimitException $e) {
    if ($e->errorCode === 'queue_full') {
        // wait for speak.ended, or interrupt
    }
}
Exception Status errorCode
ValidationException 400 invalid_request
AuthenticationException 401 invalid_api_key
PaymentRequiredException 402 payment_required (monthly limit reached)
NotFoundException 404 session_not_found, avatar_not_found, not_found
ConflictException 409 session_ended, session_not_connected, idempotency_conflict
RateLimitException 429 rate_limited, concurrency_limit, queue_full
ApiException 5xx and others gpu_unavailable (no capacity right now), maintenance
ConnectionException – Could not reach the API
TimeoutException – No response within timeout (extends ConnectionException)

All of them extend Avacast\Exception\AvacastException with errorCode, status, requestId (quote it when you contact us) and retryAfter. Branch on errorCode; messages may change.

Retries

  • 429 rate_limited is retried after retry-after. concurrency_limit and queue_full are thrown at once: close a session, or wait for the queue.
  • 5xx, timeouts and connection errors are retried for get, end, avatars->list, usage and status, and for create and speak, which send an Idempotency-Key so that a retry does not open a second session or speak twice. interrupt is not retried on these.
  • Waits are exponential (0.5 s, 1 s, 2 s … up to 8 s, ±25%), or retry-after when the API sends it. A retry-after over 60 seconds is thrown at once.

Custom HTTP client

Implement Avacast\Http\Transport (one method, send(Request): Response) to route requests through Guzzle or a PSR-18 client, or to stub the API in tests, and pass it as ['transport' => $transport].

Links