API reference
Calls
Place outbound phone calls, start browser calls, and read every call back with its transcript, costs, recordings and analysis.
- POST
/api/callsPlace an outbound phone call - POST
/api/calls/webStart a browser call - GET
/api/callsList calls - GET
/api/calls/{id}Get a call - POST
/api/calls/{id}/hangupHang up a live call - POST
/api/calls/{id}/listenGet a listen-only token for a live call - GET
/api/calls/{id}/recordingsList a call's recordings - GET
/api/calls/{id}/recordings/{recordingId}/accessGet a short-lived recording link
Place an outbound phone call
POST/api/calls
Dispatches the assistant into a fresh room and dials to over the outbound SIP trunk. With the default LiveKit runtime the request waits while the phone rings and returns once the callee answers, so allow for a long response; a call that is not answered or fails to connect answers 502 provider_error and is marked failed. With voice_provider: vapi it returns as soon as Vapi accepts the call. In both cases the 201 body says status: "ringing" (the body's literal value, not the live state): follow the call through the call.connected and call.ended webhooks, or read it back by id. The body is not wrapped in data. With mode: test the call runs the assistant's saved draft (its live config when there is none) and is a test call. 503 livekit_not_configured (or vapi_not_configured) when this deployment cannot place calls with that voice provider.
Secret API key, not read-only. How it works
Request body
assistant_idstringrequirednot emptytostringrequirednot emptyE.164 number to dial, for example
+14155550123.fromstringnot emptyOptional E.164 caller ID, registered and active in the assistant's organization and project. LiveKit calls dial from it; Vapi calls record it but dial from the Vapi phone number configured for the deployment.
metadataobjectYour own context, stored on the call and sent in its webhooks.
variablesobjectPer-call values; win over assistant defaults; unresolved keys render as empty strings.
voice_providerstringVoice runtime override; defaults to livekit.
One of
livekitvapimodestringtest runs the saved draft (live config when there is none) with test restrictions: only declared tools marked read-only that the platform runs server-side (none with their own endpoint), no transfers, DTMF or provider tools, voicemail hangs up. Its webhooks carry livemode: false and reach test subscriptions only. LiveKit only.
One of
livetestDefault
"live"
Returns
201 Ringing. LiveKit calls return room; Vapi calls return provider_call_id instead.
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404
not_found: no such assistant for this key, orfromis not an active number in the assistant's project - 409
test_number_requires_test_mode:fromis a test number and the call is live.test_mode_unsupported_provider: a test call asked for Vapi; nothing was dialled. - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address). - 502
provider_error: the call was not answered or could not be placed; it is marked failed and its room is closed - 503
livekit_not_configuredorvapi_not_configured
curl -X POST "https://api.myleadsfactory.tech/api/calls" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "asst_7d2e9b14c6a04f3e8b5d1a9c0e7f6b23",
"to": "+14155550123",
"variables": {
"first_name": "Ana"
}
}'{
"call_id": "call_5e1a7c9d2b4f4e8a9c3d6b0f1e2a4c7d",
"room": "out_call_5e1a7c9d2b4f4e8a9c3d6b0f1e2a4c7d",
"status": "ringing"
}Start a browser call
POST/api/calls/web
Mints a browser join token: connect to url with token using a LiveKit client and publish the microphone. The token lasts 15 minutes. For a live call the row exists only once the browser joins and the call starts, so GET /calls/{id} can 404 until then. With mode: test the call runs the assistant's saved draft (its live config when there is none), and its row (mode test) is created before the agent is dispatched. Call this from your server; hand only url and token to the browser. With voice_provider: vapi the response carries a web_call_url instead, when Vapi provides one. 503 when the selected voice provider is not configured.
Secret API key, not read-only. How it works
Request body
assistant_idstringrequirednot emptymetadataobjectYour own context, stored on the call and sent in its webhooks.
variablesobjectPer-call values; win over assistant defaults; unresolved keys render as empty strings.
voice_providerstringVoice runtime override; defaults to livekit.
One of
livekitvapimodestringtest runs the saved draft (live config when there is none) with test restrictions: only declared tools marked read-only that the platform runs server-side (none with their own endpoint), no transfers, DTMF or provider tools, voicemail hangs up. Its webhooks carry livemode: false and reach test subscriptions only. LiveKit only.
One of
livetestDefault
"live"
Returns
201 Created. Not wrapped in data.
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404
not_found: no such assistant for this key - 409
test_mode_unsupported_provider: a test call asked for Vapi; nothing was started. - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address). - 502 Vapi refused the call (Vapi calls only)
- 503
livekit_not_configuredorvapi_not_configured
curl -X POST "https://api.myleadsfactory.tech/api/calls/web" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "asst_7d2e9b14c6a04f3e8b5d1a9c0e7f6b23"
}'{
"call_id": "call_3b7d9f1a2c4e4b6d8f0a1c3e5b7d9f2a",
"room": "web_call_3b7d9f1a2c4e4b6d8f0a1c3e5b7d9f2a",
"token": "eyJhbGciOiJIUzI1NiJ9...",
"url": "wss://voice.example.livekit.cloud"
}List calls
GET/api/calls
Calls newest first, one cursor page at a time. Rows carry the transcript; usage lines, recordings and analysis come with the single call. A project key sees its own project; an org-wide key sees every project unless project_id narrows it.
Secret API key. How it works
Query parameters
project_idstringOnly this project's calls. With a project key, another project's id returns an empty list.
assistant_idstringOnly this assistant's calls.
statusstringOnly calls in this state.
One of
ringingin_progresscompletedfailedno_answerbusycancelledcall_typestringOnly inbound, outbound or browser calls.
One of
inboundoutboundwebqstringCase-insensitive literal substring across call id, phone numbers, and assistant id.
fromstringISO 8601 timestampCreated at or after this time (ISO 8601 with an offset).
tostringISO 8601 timestampCreated at or before this time (ISO 8601 with an offset).
limitinteger1 to 200Page size.
Default
50cursorstringOpaque next_cursor from the previous page. Legacy ISO timestamp cursors are also accepted.
modestringLive calls unless asked: test calls (console test calls, test numbers, mode test) stay out by default.
One of
livetestallDefault
"live"
Returns
200 OK
Response attributes
dataarray of Callrequired27 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequiredassistant_idstringrequiredcall_typestringrequiredOne of
inboundoutboundwebstatusstringrequiredOne of
ringingin_progresscompletedfailedno_answerbusycancelledmodestringrequiredSet when the call is created and never changed. A test call ran the assistant's draft with test restrictions (read-only declared tools run server-side, no transfers), its webhooks carry livemode: false and reach test subscriptions only, and it stays out of analytics and alerts.
One of
livetestcustomer_numberstring | nullagent_numberstring | nullroom_namestring | nullAdmins, owners, API keys and staff only.
ended_reasonstring | nullended_reason_canonicalstring | nullClosed-enum normalization of ended_reason.
started_atstring | nullISO 8601 timestampconnected_atstring | nullISO 8601 timestampended_atstring | nullISO 8601 timestampduration_msinteger | nullrecording_urlstring | nulltransfer_outcomestring | nullNormalized warm-transfer outcome when the call involved a transfer.
transcriptarray of CallTranscriptMessage | nullNull until the call has ended. Members and viewers get user and assistant turns only, with tool calls reduced to id and name.
8 attributes
rolestringrequiredOne of
userassistanttoolcontentstringrequiredtool_call_idstringTool-result turns: the tool call this answers.
tool_callsarray of object3 attributes
idstringrequirednamestringrequiredargumentsobject
occurred_atstringISO 8601 timestampseconds_from_startnumber | nullOffset from the recording start (or from when the call connected), for lining the transcript up with audio.
duration_msnumber | nullHow long the turn was spoken, in milliseconds (can be fractional).
metadataobject
voice_providerstringrequiredEvery caller. Live controls (hangup, listen) apply to livekit calls only.
One of
livekitvapiagent_configurationobject | nullPrompt snapshot. Admins, owners, API keys and staff only.
provider_metadataobject | nullAdmins, owners, API keys and staff only.
metadataobject | nullAdmins, owners, API keys and staff only.
variablesobject | nullAdmins, owners, API keys and staff only.
unresolved_variablesarray of string | nullAdmins, owners, API keys and staff only.
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
next_cursorstring | nullrequiredhas_morebooleanrequired
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/calls" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": [
{
"id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"call_type": "inbound",
"status": "ringing",
"mode": "live",
"customer_number": "string",
"agent_number": "string",
"room_name": "string",
"ended_reason": "string",
"ended_reason_canonical": "string",
"started_at": "2026-10-28T09:30:00.000Z",
"connected_at": "2026-10-28T09:30:00.000Z",
"ended_at": "2026-10-28T09:30:00.000Z",
"duration_ms": 640,
"recording_url": "https://example.com/hook",
"transfer_outcome": "string",
"transcript": [
{
"role": "user",
"content": "Hi, can I book a trip to Lisbon in May?",
"tool_call_id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"tool_calls": [
{}
],
"occurred_at": "2026-10-28T09:30:00.000Z",
"seconds_from_start": 1,
"duration_ms": 640,
"metadata": {}
}
],
"voice_provider": "livekit",
"agent_configuration": {},
"provider_metadata": {},
"metadata": {},
"variables": {
"key": "string"
},
"unresolved_variables": [
"string"
],
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
],
"next_cursor": "eyJ0IjoiMjAyNi0xMC0yOCJ9",
"has_more": true
}Get a call
GET/api/calls/{id}
One call with its transcript, usage lines, recordings, latency metrics, post-call analysis and the lifecycle events received for it. API keys see usage quantities but not prices.
Secret API key. How it works
Path parameters
idstringrequiredCall id,
call_....
Returns
200 OK
Response attributes
dataCallDetailrequired33 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequiredassistant_idstringrequiredcall_typestringrequiredOne of
inboundoutboundwebstatusstringrequiredOne of
ringingin_progresscompletedfailedno_answerbusycancelledmodestringrequiredSet when the call is created and never changed. A test call ran the assistant's draft with test restrictions (read-only declared tools run server-side, no transfers), its webhooks carry livemode: false and reach test subscriptions only, and it stays out of analytics and alerts.
One of
livetestcustomer_numberstring | nullagent_numberstring | nullroom_namestring | nullAdmins, owners, API keys and staff only.
ended_reasonstring | nullended_reason_canonicalstring | nullClosed-enum normalization of ended_reason.
started_atstring | nullISO 8601 timestampconnected_atstring | nullISO 8601 timestampended_atstring | nullISO 8601 timestampduration_msinteger | nullrecording_urlstring | nulltransfer_outcomestring | nullNormalized warm-transfer outcome when the call involved a transfer.
transcriptarray of CallTranscriptMessage | nullrequired8 attributes
rolestringrequiredOne of
userassistanttoolcontentstringrequiredtool_call_idstringTool-result turns: the tool call this answers.
tool_callsarray of object3 attributes
idstringrequirednamestringrequiredargumentsobject
occurred_atstringISO 8601 timestampseconds_from_startnumber | nullOffset from the recording start (or from when the call connected), for lining the transcript up with audio.
duration_msnumber | nullHow long the turn was spoken, in milliseconds (can be fractional).
metadataobject
voice_providerstringrequiredEvery caller. Live controls (hangup, listen) apply to livekit calls only.
One of
livekitvapiagent_configurationobject | nullPrompt snapshot. Admins, owners, API keys and staff only.
provider_metadataobject | nullAdmins, owners, API keys and staff only.
metadataobject | nullAdmins, owners, API keys and staff only.
variablesobject | nullAdmins, owners, API keys and staff only.
unresolved_variablesarray of string | nullAdmins, owners, API keys and staff only.
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestampcostsarray of CallCostAdmins, owners, API keys and staff only; amounts and prices for staff only.
10 attributes
idstringrequiredcategorystringrequiredproviderstring | nullmodelstring | nullunitstringrequiredquantitystringrequiredunit_pricestring | nullStaff only.
amountstring | nullStaff only.
currencystringStaff only.
plan_tierstring | nullStaff only.
One of
buildshipscale
recordingsarray of CallRecordingrequired14 attributes
idstringrequiredleg_typestringrequiredOne of
mainconsultpost_transferattempt_idstring | nullrequiredstatusstringrequiredOne of
pendingrecordingprocessingreadyfaileddeletedcontent_typestring | nullrequiredsize_bytesinteger | nullrequiredmin 0duration_msinteger | nullrequiredmin 0channelsinteger | nullrequiredmin 1started_atstring | nullrequiredISO 8601 timestampAudio timeline origin for transcript alignment.
ended_atstring | nullrequiredISO 8601 timestampready_atstring | nullrequiredISO 8601 timestampdeleted_atstring | nullrequiredISO 8601 timestampcreated_atstringrequiredISO 8601 timestampupdated_atstringrequiredISO 8601 timestamp
performanceCallPerformance | nullAdmins, owners, API keys and staff only.
One of 2 shapes
CallPerformance
idstringrequiredmetricsobjectrequirede2e_p50_msstring | nulle2e_p95_msstring | nulle2e_max_msstring | nullnum_interruptionsinteger | nulltotal_turnsinteger | nulllatency_summaryobject | null7 attributes
countintegerrequiredminnumberrequiredmeannumberrequiredp50numberrequiredp95numberrequiredp99numberrequiredmaxnumberrequired
Option 2
analysisobject | nullPost-call analysis when the assistant has it enabled.
2 attributes
summarystring | nullstructuredobject | null
eventsarray of WebhookEventup to 200 itemsAdmins, owners, API keys and staff only.
7 attributes
event_idstringrequiredcall_idstringrequiredeventstringrequiredorg_idstring | nullproject_idstring | nullpayloadobjectrequiredreceived_atstringrequiredISO 8601 timestamp
events_truncatedbooleanTrue when more than 200 webhook events exist for this call. Admins, owners, API keys and staff only.
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 404 Not found, or outside what the key can see
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/calls/CALL_ID" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"call_type": "inbound",
"status": "ringing",
"mode": "live",
"customer_number": "string",
"agent_number": "string",
"room_name": "string",
"ended_reason": "string",
"ended_reason_canonical": "string",
"started_at": "2026-10-28T09:30:00.000Z",
"connected_at": "2026-10-28T09:30:00.000Z",
"ended_at": "2026-10-28T09:30:00.000Z",
"duration_ms": 640,
"recording_url": "https://example.com/hook",
"transfer_outcome": "string",
"transcript": [
{
"role": "user",
"content": "Hi, can I book a trip to Lisbon in May?",
"tool_call_id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"tool_calls": [
{
"id": {},
"name": {},
"arguments": {}
}
],
"occurred_at": "2026-10-28T09:30:00.000Z",
"seconds_from_start": 1,
"duration_ms": 640,
"metadata": {}
}
],
"voice_provider": "livekit",
"agent_configuration": {},
"provider_metadata": {},
"metadata": {},
"variables": {
"key": "string"
},
"unresolved_variables": [
"string"
],
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z",
"costs": [
{
"id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"category": "string",
"provider": "string",
"model": "string",
"unit": "string",
"quantity": "string",
"unit_price": "string",
"amount": "string",
"currency": "string",
"plan_tier": "build"
}
],
"recordings": [
{
"id": "rec_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"leg_type": "main",
"attempt_id": "id_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"status": "pending",
"content_type": "string",
"size_bytes": 1,
"duration_ms": 1,
"channels": 1,
"started_at": "2026-10-28T09:30:00.000Z",
"ended_at": "2026-10-28T09:30:00.000Z",
"ready_at": "2026-10-28T09:30:00.000Z",
"deleted_at": "2026-10-28T09:30:00.000Z",
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
],
"performance": {
"id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"metrics": {},
"e2e_p50_ms": "string",
"e2e_p95_ms": "string",
"e2e_max_ms": "string",
"num_interruptions": 1,
"total_turns": 1,
"latency_summary": {
"key": {
"count": {},
"min": {},
"mean": {},
"p50": {},
"p95": {},
"p99": {},
"max": {}
}
}
},
"analysis": {
"summary": "string",
"structured": {}
},
"events": [
{
"event_id": "evt_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"call_id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"event": "string",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"payload": {},
"received_at": "2026-10-28T09:30:00.000Z"
}
],
"events_truncated": true
}
}Hang up a live call
POST/api/calls/{id}/hangup
Asks the voice runtime to end a ringing or in-progress call. The call ends shortly after, with a call.ended webhook. 409 call_not_active once it has ended, provider_not_supported for Vapi calls.
Secret API key, not read-only. How it works
Path parameters
idstringrequiredCall id,
call_....
Returns
200 Hangup requested
Response attributes
dataobjectrequired2 attributes
idstringrequiredhangup_requestedbooleanrequired
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409
call_not_activeorprovider_not_supported - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address). - 503
livekit_not_configured
curl -X POST "https://api.myleadsfactory.tech/api/calls/CALL_ID/hangup" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"id": "call_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"hangup_requested": true
}
}Get a listen-only token for a live call
POST/api/calls/{id}/listen
A LiveKit token that can hear a live call but not speak in it, for supervising from your own interface. Connect to url with token. 409 when the call is not live or is a Vapi call.
Secret API key, not read-only. How it works
Path parameters
idstringrequiredCall id,
call_....
Returns
200 Listen token
Response attributes
dataobjectrequired3 attributes
tokenstringrequiredurlstringrequiredroomstringrequired
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409
call_not_activeorprovider_not_supported - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address). - 503
livekit_not_configured
curl -X POST "https://api.myleadsfactory.tech/api/calls/CALL_ID/listen" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"token": "string",
"url": "https://example.com/hook",
"room": "string"
}
}List a call's recordings
GET/api/calls/{id}/recordings
Each recorded leg of the call with its status and length. Ask the access route for a playback URL once a recording is ready.
Secret API key. How it works
Path parameters
idstringrequiredCall id,
call_....
Returns
200 OK
Response attributes
dataarray of CallRecordingrequired14 attributes
idstringrequiredleg_typestringrequiredOne of
mainconsultpost_transferattempt_idstring | nullrequiredstatusstringrequiredOne of
pendingrecordingprocessingreadyfaileddeletedcontent_typestring | nullrequiredsize_bytesinteger | nullrequiredmin 0duration_msinteger | nullrequiredmin 0channelsinteger | nullrequiredmin 1started_atstring | nullrequiredISO 8601 timestampAudio timeline origin for transcript alignment.
ended_atstring | nullrequiredISO 8601 timestampready_atstring | nullrequiredISO 8601 timestampdeleted_atstring | nullrequiredISO 8601 timestampcreated_atstringrequiredISO 8601 timestampupdated_atstringrequiredISO 8601 timestamp
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 404 Not found, or outside what the key can see
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/calls/CALL_ID/recordings" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": [
{
"id": "rec_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"leg_type": "main",
"attempt_id": "id_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"status": "pending",
"content_type": "string",
"size_bytes": 1,
"duration_ms": 1,
"channels": 1,
"started_at": "2026-10-28T09:30:00.000Z",
"ended_at": "2026-10-28T09:30:00.000Z",
"ready_at": "2026-10-28T09:30:00.000Z",
"deleted_at": "2026-10-28T09:30:00.000Z",
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
]
}Get a short-lived recording link
GET/api/calls/{id}/recordings/{recordingId}/access
Requires access to the parent call. The response is private/no-store. URLs are generated on demand, never stored, and expire after 15 minutes: fetch a new one each time you play.
Secret API key. How it works
Path parameters
idstringrequiredCall id,
call_....recordingIdstringrequiredRecording id,
rec_..., from the call's recordings.
Query parameters
downloadbooleantruefor a URL that downloads the file;falsefor one that plays in the browser.Default
false
Returns
200 OK
Response attributes
dataRecordingAccessrequired2 attributes
urlstringrequireduriexpires_atstringrequiredISO 8601 timestamp
- 400
invalid_download:downloadmust betrueorfalse - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 404 Not found, or outside what the key can see
- 409
recording_not_ready, orrecording_storage_mismatch(stored by another deployment) - 410
recording_deleted: the recording was deleted or expired - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address). - 503
recording_storage_not_configuredorrecording_access_unavailable
curl "https://api.myleadsfactory.tech/api/calls/CALL_ID/recordings/RECORDING_ID/access" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"url": "https://example.com/hook",
"expires_at": "2026-10-28T09:30:00.000Z"
}
}