Calls
Create WebRTC or PSTN call sessions, add participants, and retrieve post-call data from a single API surface.
Create a Call
POST /v1/callsEvery call request includes one or more participants. Use transport: "webrtc" for browser users and transport: "pstn" for phone numbers.
Rymi returns 201 for WebRTC-only calls and 202 when at least one PSTN participant is queued.
For high-volume PSTN fanout, see POST /v1/calls/batch which accepts up to 500 outbound recipients.
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
agent_id | uuid | Yes | — | Agent to run for this call |
participants | Participant[] | Yes | — | One or more call participants |
metadata | object | No | {} | Custom key-value data stored on the call record |
variables | object | No | {} | Variables passed into queued PSTN jobs (accessible in agent prompt templates) |
post_call | Post-call object | No | Agent default | Per-call override for post-call intelligence. Merged with the agent's default post_call config |
Participant Object
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
transport | string | Yes | — | webrtc for browser participants, pstn for phone numbers |
identity | string | Yes | — | Browser identity string for WebRTC, or an E.164 phone number (e.g., +15551234567) for PSTN |
from_number | string | No | Tenant default | Caller ID for PSTN legs. Optional when a default number can be resolved from the tenant |
metadata | object | No | {} | Participant-scoped metadata |
Example — WebRTC Call
curl -X POST https://api.rymi.live/v1/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"participants": [
{ "transport": "webrtc", "identity": "browser-tab-1" }
],
"metadata": { "source": "sdk", "session_id": "sess_123" }
}'Response 201
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"room_name": "call_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "connecting",
"participants": [
{
"id": "participant_1",
"transport": "webrtc",
"identity": "browser-tab-1",
"status": "joining",
"access": {
"url": "wss://livekit.rymi.live",
"token": "eyJ..."
}
}
],
"agent": { "id": "550e8400-...", "name": "Aria" }
}Example — PSTN Call
curl -X POST https://api.rymi.live/v1/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"participants": [
{
"transport": "pstn",
"identity": "+15551234567",
"from_number": "+15559876543"
}
],
"metadata": { "customer_name": "Alice" },
"variables": { "customer_segment": "renewal" }
}'Response 202
{
"id": "call_abc123",
"room_name": "call_call_abc123",
"status": "queued",
"participants": [
{
"id": "participant_1",
"transport": "pstn",
"identity": "+15551234567",
"status": "queued",
"telephony_leg_id": "leg_123",
"job_id": "job_xyz"
}
]
}Example — Post-call Override
Override the agent's default post-call intelligence for a specific call:
curl -X POST https://api.rymi.live/v1/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"participants": [
{ "transport": "webrtc", "identity": "browser-user" }
],
"post_call": {
"recording": { "enabled": true },
"summary": { "enabled": true },
"structured_extraction": {
"json_schema": {
"type": "object",
"properties": {
"booked_appointment": { "type": "boolean" },
"preferred_date": { "type": "string" }
}
}
},
"evaluation": {
"criteria": "Did the agent successfully book an appointment?"
}
}
}'Agent defaults are merged with post_call — the resolved config is snapped onto the call record at creation time.
Errors
| Status | Meaning |
|---|---|
400 | Validation error (missing agent_id, invalid participants, etc.) |
401 | Missing or invalid API key |
402 | Insufficient credits |
403 | Publishable key scope violation (e.g., phone channel not allowed) |
404 | Agent not found for this tenant |
409 | DNC conflict — one or more PSTN participants are on the Do-Not-Call list |
List Calls
GET /v1/callsReturns a paginated list of call records for the authenticated tenant.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 200 | Max records to return (max 200) |
offset | integer | 0 | Records to skip |
cursor | string | — | Resume from a previous call ID when traversing call history |
status | string | — | Filter by call status: queued, ringing, in_progress, completed, or failed |
Example Request
curl "https://api.rymi.live/v1/calls?limit=50&status=completed" \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"calls": [
{
"id": "call_abc123",
"room_name": "call_call_abc123",
"agent_id": "550e8400-...",
"status": "completed",
"started_at": "2026-03-01T10:00:00Z",
"ended_at": "2026-03-01T10:05:00Z",
"bill_duration": 300,
"total_cost": 0.30,
"metadata": { "batch_id": "batch_1710" },
"intelligence_status": "completed",
"participant_count": 1,
"primary_participant": {
"identity": "+15551234567",
"transport": "pstn"
}
}
],
"total": 1,
"limit": 50,
"offset": 0,
"next_cursor": null
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Publishable keys cannot list call history |
List Active Calls
GET /v1/calls/activeReturns the same payload shape as GET /v1/calls, filtered to calls with in_progress status.
Example Request
curl https://api.rymi.live/v1/calls/active \
-H "Authorization: Bearer YOUR_API_KEY"Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
Add Participants
POST /v1/calls/:id/participantsBring a browser participant into an existing PSTN call, or queue another PSTN leg on an active session.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
participants | Participant[] | Yes | One or more participants to add |
Example Request
curl -X POST https://api.rymi.live/v1/calls/call_abc123/participants \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"participants": [
{ "transport": "webrtc", "identity": "browser-tab-2" }
]
}'Errors
| Status | Meaning |
|---|---|
400 | Invalid participant data |
401 | Missing or invalid API key |
404 | Call not found |
Call Detail
GET /v1/calls/:idReturns the expanded view of a call including participants, transcript, recording metadata, intelligence results, and event log.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Example Request
curl https://api.rymi.live/v1/calls/call_abc123 \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"id": "call_abc123",
"status": "completed",
"intelligence_status": "completed",
"bill_duration": 145,
"total_cost": 0.21,
"transcript": {
"text": "Caller: Hello\nAgent: Hi there, how can I help?",
"segments": [
{
"speaker": "user",
"text": "Hello",
"sequence": 0,
"started_at_ms": 0,
"ended_at_ms": 900,
"is_final": true,
"source": "runtime"
},
{
"speaker": "agent",
"text": "Hi there, how can I help?",
"sequence": 1,
"started_at_ms": 1000,
"ended_at_ms": 2500,
"is_final": true,
"source": "runtime"
}
],
"raw": [
{
"id": "t_1",
"type": "user_input",
"response": "Hello"
}
]
},
"recording": {
"id": "rec_1",
"status": "ready",
"format": "wav",
"provider_recording_id": "prov_123",
"metadata": {
"stereo_mix": {
"signed_url": "https://storage.rymi.live/recordings/..."
}
}
},
"intelligence": {
"status": "completed",
"summary": "Caller asked for support and the agent resolved the issue.",
"sentiment": "neutral",
"structured_data": {
"customer_intent": "support"
},
"evaluation": {
"passed": true,
"score": 1,
"reasoning": "The issue was resolved successfully."
},
"errors": []
},
"events": [
{
"id": "evt_1",
"level": "info",
"source": "post_call",
"message": "Post-call analysis completed."
}
]
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Publishable keys cannot fetch call details |
404 | Call not found |
Call Summary
GET /v1/calls/:id/summaryReturns the persisted post-call summary and sentiment. This endpoint does not run ad hoc LLM analysis at request time — it returns previously computed results.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Example Request
curl https://api.rymi.live/v1/calls/call_abc123/summary \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"status": "completed",
"sentiment": "positive",
"summary": "The caller confirmed the appointment and no follow-up was needed."
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
404 | Call not found or summary not yet available |
Call Transcript
GET /v1/calls/:id/transcriptReturns the raw and normalized transcript for a completed call.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Example Request
curl https://api.rymi.live/v1/calls/call_abc123/transcript \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"transcript": [
{
"id": "t_1",
"type": "user_input",
"response": "Hello?",
"speaker": "user",
"sequence": 0,
"started_at_ms": 0,
"ended_at_ms": 850,
"is_final": true,
"source": "runtime"
}
],
"text": "Caller: Hello?",
"segments": [
{
"speaker": "user",
"text": "Hello?",
"sequence": 0,
"started_at_ms": 0,
"ended_at_ms": 850,
"is_final": true,
"source": "runtime"
}
]
}Transcript Segment Fields
| Field | Type | Description |
|---|---|---|
speaker | string | user or agent |
text | string | Transcribed text |
sequence | integer | Zero-based segment order |
started_at_ms | integer | Segment start time in milliseconds from call start |
ended_at_ms | integer | Segment end time in milliseconds from call start |
is_final | boolean | Whether this is a final (non-interim) transcript segment |
source | string | Transcript source (e.g., runtime) |
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
404 | Call not found or transcript not yet available |
Call Recording
GET /v1/calls/:id/recordingReturns the latest recording metadata plus time-limited signed URLs for audio download.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Example Request
curl https://api.rymi.live/v1/calls/call_abc123/recording \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"call_id": "call_abc123",
"recording": {
"id": "rec_1",
"status": "ready",
"format": "wav",
"provider_recording_id": "prov_123",
"metadata": {
"stereo_mix": {
"signed_url": "https://storage.rymi.live/recordings/..."
}
}
}
}Recording Status Values
| Status | Description |
|---|---|
pending | Recording is being processed |
ready | Recording is available for download |
failed | Recording processing failed |
disabled | Recording was not enabled for this call |
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Publishable keys cannot access recordings |
404 | Call not found or recording not available |
End a Call
POST /v1/calls/:id/endForce-ends an active call by closing the LiveKit room. The call transitions to completed and post-call processing is triggered.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Example Request
curl -X POST https://api.rymi.live/v1/calls/call_abc123/end \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"status": "ended",
"id": "call_abc123",
"message": "Call has been terminated."
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Publishable keys cannot end calls |
404 | Call not found |
409 | Call is already completed or failed |
Call Events
GET /v1/calls/:id/eventsReturns the event log for a specific call, including lifecycle transitions and post-call processing events. Useful for building real-time dashboards and debugging call flows.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max records to return (max 200) |
offset | integer | 0 | Records to skip |
Example Request
curl "https://api.rymi.live/v1/calls/call_abc123/events?limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"events": [
{
"id": "evt_1",
"call_id": "call_abc123",
"level": "info",
"source": "lifecycle",
"message": "Call created",
"created_at": "2026-03-01T10:00:00Z"
},
{
"id": "evt_2",
"call_id": "call_abc123",
"level": "info",
"source": "lifecycle",
"message": "PSTN leg connected",
"created_at": "2026-03-01T10:00:05Z"
},
{
"id": "evt_3",
"call_id": "call_abc123",
"level": "info",
"source": "post_call",
"message": "Post-call analysis completed.",
"created_at": "2026-03-01T10:05:30Z"
}
],
"total": 3,
"offset": 0,
"limit": 20
}Event Fields
| Field | Type | Description |
|---|---|---|
id | string | Event ID |
call_id | string | Associated call ID |
level | string | info, warning, or error |
source | string | Event source: lifecycle, post_call, telephony, livekit |
message | string | Human-readable event description |
created_at | string | ISO 8601 timestamp |
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
403 | Publishable keys cannot access call events |
404 | Call not found |
Reprocess Post-call Intelligence
POST /v1/calls/:id/reprocessQueues post-call intelligence again for a completed call. Useful when you've updated the agent's extraction schema or evaluation criteria and want to re-run analysis.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Call ID (must be completed) |
Example Request
curl -X POST https://api.rymi.live/v1/calls/call_abc123/reprocess \
-H "Authorization: Bearer YOUR_API_KEY"Response 202
{
"status": "queued",
"job_id": "job_123",
"message": "Post-call intelligence reprocessing has been queued."
}Errors
| Status | Meaning |
|---|---|
400 | Call is not in completed status |
401 | Missing or invalid API key |
403 | Publishable keys cannot trigger reprocessing |
404 | Call not found |
Queue Stats
GET /v1/calls/queue/statsReturns the BullMQ queue counts used for PSTN dialing.
Example Request
curl https://api.rymi.live/v1/calls/queue/stats \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"waiting": 12,
"active": 2,
"completed": 340,
"failed": 4
}Publishable Key Rules
When using a publishable key (sb_publishable_...) to create calls:
- WebRTC: Allowed when the key permits the
webchannel. - PSTN: Allowed only when the key permits the
phonechannel. - Phone limit: Publishable phone calls must target exactly one PSTN participant and cannot override
agent_idorfrom_number. - Read restrictions: Publishable keys cannot list call history, fetch recordings, access transcripts, or trigger reprocessing.

