Teler Voice API

Programmable voice/telephony API. Places and controls live voice calls (initiate, play audio, DTMF, transfer, hangup), streams bidirectional call audio to AI agents over a WebSocket media channel, and provisions programmable SIP trunking (trunks, IP ACLs, virtual numbers). REST resources for calls, voice apps, virtual numbers, SIP trunks/calls, webhook events, recordings and secrets use cursor pagination. Served from https://api.frejun.ai and authenticated with an x-api-key header. Backed by official Python (teler) and Node (@frejun/teler) SDKs.

Operations 42

POST /api/v1/calls/initiate (Deprecated) Initiate a call #
POST /api/v1/voice/calls/initiate Initiate a call #
GET /api/v1/voice/calls List calls #
GET /api/v1/voice/calls/{call_id} Retrieve a call #
GET /api/v1/voice/calls/{call_id}/legs List call legs #
POST /api/v1/voice/apps Create a voice app #
GET /api/v1/voice/apps List voice apps #
GET /api/v1/voice/apps/{voice_app_id} Retrieve a voice app #
PATCH /api/v1/voice/apps/{voice_app_id} Update a voice app #
DELETE /api/v1/voice/apps/{voice_app_id} Delete a voice app #
GET /api/v1/voice/apps/{voice_app_id}/virtual-numbers List virtual numbers for a voice app #
POST /api/v1/voice/calls/{call_id}/hangup Hang up a call #
POST /api/v1/voice/calls/{call_id}/mute Mute or unmute a call leg #
POST /api/v1/voice/calls/{call_id}/dtmf Send DTMF tones on a call leg #
POST /api/v1/voice/calls/{call_id}/play Play an audio file into the call #
POST /api/v1/voice/calls/{call_id}/transfer Transfer a call #
GET /api/v1/virtual-numbers List virtual numbers #
POST /api/v1/virtual-numbers/assign Assign virtual numbers #
POST /api/v1/virtual-numbers/unassign Unassign virtual numbers #
PATCH /api/v1/virtual-numbers/{vn_id} Update a virtual number #
GET /api/v1/sip/calls List SIP calls #
GET /api/v1/sip/calls/{call_id} Retrieve a SIP call #
POST /api/v1/sip/trunks Create a SIP trunk #
GET /api/v1/sip/trunks List SIP trunks #
GET /api/v1/sip/trunks/{trunk_id} Retrieve a SIP trunk #
PATCH /api/v1/sip/trunks/{trunk_id} Update a SIP trunk #
DELETE /api/v1/sip/trunks/{trunk_id} Delete a SIP trunk #
GET /api/v1/sip/trunks/{trunk_id}/virtual-numbers List virtual numbers for a SIP trunk #
POST /api/v1/sip/ip-acls Create an IP access control list #
GET /api/v1/sip/ip-acls List IP access control lists #
GET /api/v1/sip/ip-acls/{ip_acl_id} Retrieve an IP access control list #
PATCH /api/v1/sip/ip-acls/{ip_acl_id} Update an IP access control list #
DELETE /api/v1/sip/ip-acls/{ip_acl_id} Delete an IP access control list #
GET /api/v1/events List webhook events #
GET /api/v1/events/{event_id} Retrieve a webhook event #
POST /api/v1/events/{event_id}/redeliver Redeliver a webhook event #
GET /api/v1/recordings Get a recording download URL #
POST /api/v1/secrets Create a secret #
GET /api/v1/secrets List secrets #
GET /api/v1/secrets/{secret_id} Retrieve a secret #
PATCH /api/v1/secrets/{secret_id} Update a secret #
DELETE /api/v1/secrets/{secret_id} Delete a secret #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/teler-voice-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

frejun-teler-openapi.json Raw ↑
{"openapi":"3.1.0","info":{"title":"Teler API Reference","summary":"Programmable voice infrastructure for AI agents.","description":"The Teler API lets you place and control programmable voice calls, stream live\naudio to AI agents, and observe everything that happens on a call in real time.\n\nAll endpoints are served over HTTPS from `https://api.frejun.ai` and speak JSON.\nAuthenticate every request with your secret API key in the `x-api-key` header:\n\n```bash\ncurl https://api.frejun.ai/api/v1/voice/calls \\\n  -H \"x-api-key: $TELER_API_KEY\"\n```\n\nKeys are account-scoped and grant full access — treat them like passwords, keep\nthem server-side, and rotate them from the\n[Teler dashboard](https://platform.frejun.ai/signup) if one leaks. A missing or\ninvalid key returns `403`.\n\nGuides for resource identifiers, pagination, errors, idempotency, webhooks, and\nthe official Python and Node.js SDKs live in the\n[Teler documentation](https://frejun.com/docs/teler/).\n","contact":{"name":"Teler support","email":"support@frejun.com"},"version":"0.1.0"},"servers":[{"url":"https://api.frejun.ai","description":"Production"}],"paths":{"/api/v1/calls/initiate":{"post":{"tags":["Voice / Calls (legacy)"],"summary":"(Deprecated) Initiate a call","description":"**Deprecated.** Use `POST /api/v1/voice/calls/initiate` (Voice / Calls) instead. This path is kept only for backwards compatibility and will be removed in a future version.","operationId":"initiate_call_legacy","deprecated":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallInitiateRequest"}}}},"responses":{"202":{"description":"The call was accepted and is being placed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallInitiateResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"502":{"description":"Teler could not reach the call-control service.","content":{"application/json":{"example":{"success":false,"message":"The call could not be initiated. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"The call could not be initiated in time.","content":{"application/json":{"example":{"success":false,"message":"The call could not be initiated in time. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/voice/calls/initiate":{"post":{"tags":["Voice / Calls"],"summary":"Initiate a call","description":"Place an outbound call. Teler dials `to_number` from `from_number`, and once the call connects it fetches your `flow_url` to drive the conversation. Status updates are delivered to `status_callback_url` for the lifetime of the call.\n\nThe call is accepted asynchronously: a `202` means Teler has queued the call, not that the callee has answered. Track progress via webhooks or by polling **Retrieve a call**.","operationId":"initiate_call","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallInitiateRequest"}}}},"responses":{"202":{"description":"The call was accepted and is being placed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallInitiateResponse"}}}},"400":{"description":"The call was rejected before dialing. The `code` and `message` are propagated from the call-control service and describe the specific reason; the values shown here are illustrative.","content":{"application/json":{"example":{"success":false,"message":"The from_number is not provisioned for outbound calls.","code":"from_number_not_provisioned"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"502":{"description":"Teler could not reach the call-control service.","content":{"application/json":{"example":{"success":false,"message":"The call could not be initiated. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"The call could not be initiated in time.","content":{"application/json":{"example":{"success":false,"message":"The call could not be initiated in time. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/voice/calls":{"get":{"tags":["Voice / Calls"],"summary":"List calls","description":"List your account's calls, newest first. Filter by state, numbers, or creation time, and page through results with cursors (see the Pagination section in the overview).","operationId":"list_voice_calls","parameters":[{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CallSessionState"},{"type":"null"}],"title":"State"}},{"name":"from_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Number"}},{"name":"to_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Number"}},{"name":"created_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created After"}},{"name":"created_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created Before"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor — page toward older rows (next page).","title":"Cursor After"},"description":"Opaque cursor — page toward older rows (next page)."},{"name":"cursor_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor — page toward newer rows (previous page).","title":"Cursor Before"},"description":"Opaque cursor — page toward newer rows (previous page)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_CallSessionResponse_"}}}},"400":{"description":"The pagination cursor is invalid or has expired.","content":{"application/json":{"example":{"success":false,"message":"The pagination cursor is invalid or has expired."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}":{"get":{"tags":["Voice / Calls"],"summary":"Retrieve a call","description":"Retrieve a single call by its identifier, including its legs.","operationId":"retrieve_voice_call","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSessionResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}/legs":{"get":{"tags":["Voice / Calls"],"summary":"List call legs","description":"List the individual legs that make up a call, in creation order.","operationId":"list_call_legs","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_CallLegResponse_"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/voice/apps":{"post":{"tags":["Voice / Apps"],"summary":"Create a voice app","operationId":"create_voice_app","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAppCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAppResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}},"get":{"tags":["Voice / Apps"],"summary":"List voice apps","operationId":"list_voice_apps","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/Status"}},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor After"}},{"name":"cursor_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_CallAppResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/voice/apps/{voice_app_id}":{"get":{"tags":["Voice / Apps"],"summary":"Retrieve a voice app","operationId":"retrieve_voice_app","parameters":[{"name":"voice_app_id","in":"path","required":true,"schema":{"type":"string","title":"Voice App Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAppResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}},"patch":{"tags":["Voice / Apps"],"summary":"Update a voice app","operationId":"update_voice_app","parameters":[{"name":"voice_app_id","in":"path","required":true,"schema":{"type":"string","title":"Voice App Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAppUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAppResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}},"delete":{"tags":["Voice / Apps"],"summary":"Delete a voice app","operationId":"delete_voice_app","parameters":[{"name":"voice_app_id","in":"path","required":true,"schema":{"type":"string","title":"Voice App Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefaultResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/voice/apps/{voice_app_id}/virtual-numbers":{"get":{"tags":["Voice / Apps"],"summary":"List virtual numbers for a voice app","operationId":"list_voice_app_virtual_numbers","parameters":[{"name":"voice_app_id","in":"path","required":true,"schema":{"type":"string","title":"Voice App Id"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Limit"}},{"name":"cursor_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor After"}},{"name":"cursor_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_VNListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}/hangup":{"post":{"tags":["Voice / Call Controls"],"summary":"Hang up a call","description":"End a call, or a single leg of it. Omit `leg_id` to hang up the entire call; supply it to drop just that leg.","operationId":"hangup_call","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HangupRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MutationAccepted"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The call is not in a state that accepts controls (e.g. it has already ended). `code` is one of `call_not_live`, `leg_not_found`, `call_not_controllable`, or `feature_not_enabled`.","content":{"application/json":{"example":{"success":false,"message":"The call is not in a state that accepts controls.","code":"call_not_live","type":"invalid_state"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"503":{"description":"The call-control service is temporarily unavailable. Safe to retry.","content":{"application/json":{"example":{"success":false,"message":"The action could not be applied. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}/mute":{"post":{"tags":["Voice / Call Controls"],"summary":"Mute or unmute a call leg","description":"Mute (`on: true`) or unmute (`on: false`) a specific leg of a call.","operationId":"mute_call","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MuteRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MutationAccepted"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The call is not in a state that accepts controls (e.g. it has already ended). `code` is one of `call_not_live`, `leg_not_found`, `call_not_controllable`, or `feature_not_enabled`.","content":{"application/json":{"example":{"success":false,"message":"The call is not in a state that accepts controls.","code":"call_not_live","type":"invalid_state"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"503":{"description":"The call-control service is temporarily unavailable. Safe to retry.","content":{"application/json":{"example":{"success":false,"message":"The action could not be applied. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}/dtmf":{"post":{"tags":["Voice / Call Controls"],"summary":"Send DTMF tones on a call leg","description":"Send DTMF (touch-tone) digits on a call leg, e.g. to navigate an IVR.","operationId":"send_dtmf","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DtmfRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MutationAccepted"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The call is not in a state that accepts controls (e.g. it has already ended). `code` is one of `call_not_live`, `leg_not_found`, `call_not_controllable`, or `feature_not_enabled`.","content":{"application/json":{"example":{"success":false,"message":"The call is not in a state that accepts controls.","code":"call_not_live","type":"invalid_state"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"503":{"description":"The call-control service is temporarily unavailable. Safe to retry.","content":{"application/json":{"example":{"success":false,"message":"The action could not be applied. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}/play":{"post":{"tags":["Voice / Call Controls"],"summary":"Play an audio file into the call","description":"Play an audio file into the call. The response includes a `playback_id` you can use to correlate playback lifecycle webhooks.","operationId":"play_audio","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MutationAccepted"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The call is not in a state that accepts controls (e.g. it has already ended). `code` is one of `call_not_live`, `leg_not_found`, `call_not_controllable`, or `feature_not_enabled`.","content":{"application/json":{"example":{"success":false,"message":"The call is not in a state that accepts controls.","code":"call_not_live","type":"invalid_state"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"503":{"description":"The call-control service is temporarily unavailable. Safe to retry.","content":{"application/json":{"example":{"success":false,"message":"The action could not be applied. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/voice/calls/{call_id}/transfer":{"post":{"tags":["Voice / Operations"],"summary":"Transfer a call","description":"Transfer an in-progress call to a new destination — a phone number (`pstn`) or a SIP URI (`sip`). Only `cold` transfers are currently supported. A call can have only one transfer in flight at a time.\n\nThe transfer is accepted asynchronously; a `202` means it has been started, not that the target has answered.","operationId":"transfer_call","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferRequest"}}}},"responses":{"202":{"description":"The transfer was accepted and is being placed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferAccepted"}}}},"400":{"description":"The transfer target or mode is invalid (e.g. missing `number` for a `pstn` target, or an unsupported mode).","content":{"application/json":{"example":{"success":false,"message":"target.number is required when kind='pstn'.","code":"invalid_target"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"A transfer is already in progress for this call.","content":{"application/json":{"example":{"success":false,"message":"A transfer is already in progress for this call.","code":"transfer_in_progress","type":"invalid_state"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"503":{"description":"The call-control service is temporarily unavailable. Safe to retry.","content":{"application/json":{"example":{"success":false,"message":"The transfer could not be started. Please try again."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/virtual-numbers":{"get":{"tags":["Virtual Numbers"],"summary":"List virtual numbers","operationId":"list_virtual_numbers","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"voice_app","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Voice App"}},{"name":"sip_trunk","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Sip Trunk"}},{"name":"cursor_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor After"}},{"name":"cursor_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_VNListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/virtual-numbers/assign":{"post":{"tags":["Virtual Numbers"],"summary":"Assign virtual numbers","operationId":"assign_virtual_numbers","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"voice_app","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Voice App"}},{"name":"sip_trunk","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Sip Trunk"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignVNsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefaultResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/virtual-numbers/unassign":{"post":{"tags":["Virtual Numbers"],"summary":"Unassign virtual numbers","operationId":"unassign_virtual_numbers","parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"voice_app","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Voice App"}},{"name":"sip_trunk","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Sip Trunk"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnassignVNsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefaultResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/virtual-numbers/{vn_id}":{"patch":{"tags":["Virtual Numbers"],"summary":"Update a virtual number","operationId":"update_virtual_number","parameters":[{"name":"vn_id","in":"path","required":true,"schema":{"type":"string","title":"Vn Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VNUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VNResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/sip/calls":{"get":{"tags":["SIP / Calls"],"summary":"List SIP calls","description":"List calls that traversed your SIP trunks, newest first. Filter by trunk, numbers, or creation time, and page with cursors (see the Pagination section in the overview).","operationId":"list_sip_calls","parameters":[{"name":"trunk_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by SIP trunk. Accepts the `st_<ULID>` identifier.","title":"Trunk Id"},"description":"Filter by SIP trunk. Accepts the `st_<ULID>` identifier."},{"name":"from_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Number"}},{"name":"to_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Number"}},{"name":"created_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created After"}},{"name":"created_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created Before"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor After"}},{"name":"cursor_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CursorPage_SipCallResponse_"}}}},"400":{"description":"The pagination cursor is invalid or has expired.","content":{"application/json":{"example":{"success":false,"message":"The pagination cursor is invalid or has expired."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The request body or query parameters failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/sip/calls/{call_id}":{"get":{"tags":["SIP / Calls"],"summary":"Retrieve a SIP call","description":"Retrieve a single SIP call by its identifier.","operationId":"retrieve_sip_call","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SipCallResponse"}}}},"403":{"description":"The `x-api-key` header is missing or invalid.","content":{"application/json":{"example":{"success":false,"message":"Invalid API Key."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No call matches the supplied identifier for this account.","content":{"application/json":{"example":{"success":false,"message":"The requested call was not found."},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/sip/trunks":{"post":{"tags":["SIP / Trunks"],"summary":"Create a SIP trunk","operationId":"create_sip_trunk","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SipTrunkCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SipTrunkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}},"get":{"tags":["SIP / Trunks"],"summary":"List SIP trunks","operationId":"list_sip_trunks","parameters":[{"name":"limit","in":"query","required":false,"sch

# --- truncated at 32 KB (101 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/frejun-teler/refs/heads/main/openapi/frejun-teler-openapi.json