API reference
Access tokens
An access token is a short-lived JWT, minted on your server, that a browser or mobile WebRTC client presents to register a softphone and place or receive calls. Your long-lived API key signs the request but never leaves your backend — the client only ever holds the disposable JWT. Tokens carry a voice grant and a tight TTL, so a leaked token expires in minutes and grants nothing beyond voice. The underlying short-lived-JWT model and WebRTC softphone are shipped in Dial; this public token-minting endpoint is in developer preview.
Server-side only
This endpoint is authenticated with your $TELVOX_API_KEY and must be called from your backend. Never ship the API key to a browser or mobile app. The pattern is: your client authenticates to your server, your server mints a token scoped to that user, and you return only the JWT. The API secret never reaches the client.
Base URL
https://api.telvox.dev/v1Token properties
A minted access token is represented by the following fields.
| Property | Type | Description |
|---|---|---|
| token | string (JWT) | The signed JWT your client presents to register the WebRTC softphone. Short-lived; treat it as a bearer credential. |
| identity | string | The client identity encoded in the token — your own opaque user reference (e.g. agent-204). Used to address inbound calls to this client. |
| grants | object | The capabilities embedded in the token. Currently a single voice grant; see the grant schema below. |
| ttl | integer | Lifetime in seconds. Defaults to 600 (10 minutes); capped at 900 (15 minutes). Mint a fresh token rather than issuing long-lived ones. |
| expires_at | string | ISO 8601 timestamp when the token expires. After this the client must request a new token from your server. |
Voice grant schema
The grant is what a token authorizes. Connect tokens carry a single voice grant — there is no broad account access embedded in the JWT.
| Grant field | Type | Description |
|---|---|---|
| voicerequired | object | Enables placing and receiving calls over WebRTC. Presence of this grant is what makes the token a voice token. |
| voice.incoming_allowed | boolean | Whether calls may be routed to this client identity. Defaults to true. |
| voice.answer_url | string | Optional answer URL applied to outbound calls this client originates, overriding the application default. |
Mint an access token
/v1/access-tokensIssue a short-lived JWT with a voice grant for a single client identity. Call this from your server.
# SERVER-SIDE ONLY — never expose $TELVOX_API_KEY to the browser
curl -X POST https://api.telvox.dev/v1/access-tokens \
-H "Authorization: Bearer $TELVOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"identity": "agent-204",
"grant": "voice",
"ttl": 600
}'| Parameter | Type | Description |
|---|---|---|
| identityrequired | string | Your opaque client identity. Becomes the addressable handle for this WebRTC client. |
| grant | string | Grant to embed. Only "voice" is supported. Defaults to "voice". |
| ttl | integer | Requested lifetime in seconds. Clamped to the 900s maximum. |
| incoming_allowed | boolean | Allow inbound calls to be routed to this identity. Defaults to true. |
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6...",
"identity": "agent-204",
"grants": {
"voice": { "incoming_allowed": true }
},
"ttl": 600,
"expires_at": "2026-06-21T17:14:11Z"
}TTL & rotation
Tokens default to a 10-minute TTL and are capped at 15 minutes. Rather than extending a token's life, have the client request a fresh one from your server shortly before expires_at. Short lifetimes keep the blast radius of a leaked token to minutes, and rotation happens entirely through your own authenticated endpoint.
Client usage
The client never calls TelVox to obtain a token. It fetches the JWT from your server and hands it to the WebRTC client to register.
// The client fetches a fresh token from YOUR server, never from TelVox.
const { token } = await fetch("/token").then((r) => r.json());
// Hand the JWT to the WebRTC client to register the softphone.
const device = new TelVox.Device(token);
await device.register();
// Refresh before expiry — request a new token from your server.