API reference
The Fonada REST API manages your BYO media-stream configuration and controls live streaming sessions (consult and conference). The real-time media protocol itself runs over WebSocket and is documented in the Audio Streaming overview and Protocol pages.
Base URL
https://api.fonada.example/v1
This value is a placeholder. Fonada provides the production service host during onboarding. Consult and conference examples also use https://<service-host>.
Authentication
All requests require a bearer token. OpenAPI documents the format as JWT:
Authorization: Bearer <token>
Conventions
- All request and response bodies are application/json.
- Phone numbers are passed bare; Fonada applies the dialling prefix, operator, and technology from your account configuration.
session_idis the live identifier delivered insession_startand returned by GET /sessions.
GET /media-stream
Get current media stream configuration.
- Requires scope media:manage.
- Returns the tenant's current BYO media-stream config (URL, codec, sample rates, secret hint).
- Never returns the plaintext media_secret.
- Returns 404 when no config is registered for the tenant.
- Also returns 401, 403, or 503 as listed in Error responses.
{
"tenant": "acme-voicebot",
"media_ws_url": "wss://voice.acme.com/stream",
"codec": "slin16",
"input_sample_rate": 16000,
"output_sample_rate": 16000,
"channels": 1,
"encoding": "binary",
"chunk_bytes": 640,
"secret_hint": "…a1b2"
}PUT /media-stream
Register or update media stream configuration.
- Requires scope media:manage.
- Registers or updates the tenant's BYO media-stream endpoint.
- The media_secret is write-only and is never returned by any read endpoint.
- Returns 200 with MediaStreamConfig, or 400 / 401 / 403.
{
"media_ws_url": "wss://voice.acme.com/stream",
"codec": "slin16",
"input_sample_rate": 16000,
"output_sample_rate": 16000,
"encoding": "binary",
"chunk_bytes": 640,
"media_secret": "s3cr3t-rotate-me"
}GET /sessions
Returns all live streaming sessions for the tenant, each identified by its session_id. Use this to discover the id needed by the consult and conference endpoints.
[
{
"session_id": "1711234567.42",
"customer_phone": "919876543210",
"direction": "inbound",
"started_at": "2026-08-18T09:12:04Z",
"conferenceNumbers": []
}
]GET /sessions/{session_id}
Returns session detail, including conferenceNumbers. Returns 401 if unauthorised and 404 if the session is not found.
{
"session_id": "1711234567.42",
"customer_phone": "919876543210",
"direction": "inbound",
"started_at": "2026-08-18T09:12:04Z",
"conferenceNumbers": ["7042009848"]
}POST /sessions/{session_id}/consult
Puts the caller on hold and dials a second party, bridging them privately with the bot. Synchronous — blocks until the party answers, the dial fails, or the timeout elapses (default 20s + 5s margin). Set your HTTP read-timeout to at least 30 seconds.
Request body: calledParty (bare number), optional callerId. Full field tables, status codes, and curl examples are on Consult & conference.
{
"sessionId": "1711234567.42",
"consultId": "consult-1711234567.42",
"status": "answered",
"dialStatus": "ANSWER"
}POST /sessions/{session_id}/conference
Adds a party to, or removes a party from, the live call. Everyone in the bridge hears everyone. Switched by the action field (add or delete). Required fields: action, number. Optional callerId on add.
Returns 200, 400, 401, 404, or 409. See Consult & conference for complete request and response tables.
Schemas
MediaStreamConfig
| Field | Type | Notes |
|---|---|---|
tenant | string | Tenant identifier. |
media_ws_url | uri string | Your WebSocket endpoint. |
codec | string | Example slin16 (Asterisk-style name for PCM16). |
input_sample_rate | integer | 8000 or 16000. |
output_sample_rate | integer | 8000 or 16000. |
channels | integer | Always 1. |
encoding | string | binary or base64. |
chunk_bytes | integer | Example 640. |
secret_hint | string | Masked hint only. Never the plaintext media_secret. |
MediaStreamUpsert
| Field | Type | Notes |
|---|---|---|
media_ws_url | uri string | Required. |
codec | string | Example slin16. |
input_sample_rate | integer | 8000 or 16000. |
output_sample_rate | integer | 8000 or 16000. |
encoding | string | binary or base64. |
chunk_bytes | integer | Example 640. |
media_secret | string | Write-only. Never returned by any read endpoint. |
Session
| Field | Type | Notes |
|---|---|---|
session_id | string | Live id from session_start. |
customer_phone | string | End-user number. |
direction | string | inbound or outbound. |
started_at | date-time | ISO timestamp. |
conferenceNumbers | string[] | Current conference members. |
ConsultRequest
| Field | Type | Notes |
|---|---|---|
calledParty | string | Bare number of the second party. Fonada applies prefix, operator, and technology. |
callerId | string | Bare Caller ID to present. Falls back to the configured default. |
ConsultResult
| Field | Type | Notes |
|---|---|---|
sessionId | string | The session id. |
consultId | string | consult-<sessionId>. |
status | string | answered, failed, or timeout. |
dialStatus | string | ANSWER, NOANSWER, BUSY, CONGESTION, or CHANUNAVAIL. |
cause | integer | Q.850 cause; present only when status=failed. |
causeText | string | Present only when status=failed. |
ConferenceRequest
| Field | Type | Notes |
|---|---|---|
action | string | Required. add or delete. |
number | string | Required. Bare number. |
callerId | string | add only. |
ConferenceResult
| Field | Type | Notes |
|---|---|---|
sessionId | string | The session id. |
number | string | The bare number. |
channelId | string | conf-<sessionId>-<number>. |
status | string | answered, failed, or timeout. |
dialStatus | string | Guide values: ANSWER, NOANSWER, BUSY, CONGESTION, CHANUNAVAIL. OpenAPI lists ANSWER, NOANSWER, BUSY. |
Error responses
Error bodies use error and message string fields.
| Code | Name | Meaning |
|---|---|---|
| 400 | Bad Request | Malformed request. |
| 401 | Unauthorized | Missing or invalid credentials. |
| 403 | Forbidden | Insufficient scope (for example media:manage). |
| 404 | Not Found | Resource not found. GET /media-stream returns 404 when no config is registered. |
| 409 | Conflict | Conflicting state (conference add). |
| 500 | Server Error | Could not place the call. |
| 503 | Unavailable | Service temporarily unavailable (GET /media-stream). |