Trillet AI logo

API conventions

Idempotency, errors, pagination, versioning and rate limits for the Voice Engine API.

Coming soon. The Voice Engine API is in development. This page describes the planned design; details may change before release.

  • Base URL: https://api.trillet.ai/partner/v1
  • Format: JSON request and response bodies, UTF-8, timestamps in ISO 8601 UTC.
  • IDs: Trillet IDs are opaque strings. Store them as strings.

Idempotency

Networks fail. Send an Idempotency-Key header on every request that creates something, so a retry never creates it twice. Tenant creation requires one.

curl -X POST https://api.trillet.ai/partner/v1/tenants \
  -H "Authorization: Bearer tpk_live_..." \
  -H "Idempotency-Key: create-tenant-cust_8842" \
  -H "Content-Type: application/json" \
  -d '{ "externalId": "cust_8842", "name": "Harbour Dental" }'
SituationResult
First request with a keyRuns normally. The response is stored for 24 hours.
Retry with the same key and the same bodyThe stored response is returned with Idempotent-Replayed: true. Nothing runs twice.
Same key, different body422 idempotency_key_reused
Same key while the first request is still running409 idempotency_key_in_use. Retry after Retry-After.
The first request failed with a 5xxNot stored. A retry runs again.

Keys are 1 to 255 printable characters and are scoped to your partner account. A UUID, or your own operation ID, works well.

Errors

Every error has the same shape:

{
  "error": {
    "type": "invalid_request",
    "code": "tenant_deleted_restorable",
    "message": "A deleted tenant with this externalId can still be restored.",
    "param": "externalId",
    "requestId": "req_7Qe2..."
  }
}

Handle errors by code, not by message. Include requestId when you contact support.

StatusMeaning
400The request is malformed or a required field is missing
401Authentication failed
403Not allowed for this key
404Not found, or not yours
409Conflict, for example a duplicate externalId or a request still in progress
422The request is well formed but cannot be applied
429Rate limited
5xxA problem on our side. Safe to retry with the same Idempotency-Key.

Pagination

List endpoints return a page and a cursor:

{
  "data": [ { "id": "ten_1" }, { "id": "ten_2" } ],
  "hasMore": true,
  "nextCursor": "ten_2"
}

Pass limit (1 to 100, default 20) and starting_after=<nextCursor> to get the next page.

Versioning

The major version is in the path (/partner/v1). Within a version we only add things: new endpoints, new optional fields, new event types. Your code should ignore fields and event types it does not recognise.

Breaking changes ship as a new major version, with notice and an overlap period. Webhook payloads carry an apiVersion field.

Rate limits

Limits apply per key. The default is 100 requests per second in bursts and 6,000 per minute. A 429 response includes Retry-After. Contact us if your integration needs more.