Skip to content

Calls ​

Create WebRTC or PSTN call sessions, add participants, and retrieve post-call data from a single API surface.

Create a Call ​

POST/v1/calls

Every 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 ​

FieldTypeRequiredDefaultDescription
agent_iduuidYes-Agent to run for this call
participantsParticipant[]Yes-One or more call participants
metadataobjectNo{}Custom key-value data stored on the call record
variablesobjectNo{}Variables passed into queued PSTN jobs (accessible in agent prompt templates)
post_callPost-call objectNoAgent defaultPer-call override for post-call intelligence. Merged with the agent's default post_call config

Participant Object ​

FieldTypeRequiredDefaultDescription
transportstringYes-webrtc for browser participants, pstn for phone numbers
identitystringYes-Browser identity string for WebRTC, or an E.164 phone number (e.g., +15551234567) for PSTN
from_numberstringNoTenant defaultCaller ID for PSTN legs. Optional when a default number can be resolved from the tenant
metadataobjectNo{}Participant-scoped metadata

Example: WebRTC Call ​

bash
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" }
  }'
ts
const call = await rymi.calls.create({
  agent_id: "550e8400-e29b-41d4-a716-446655440000",
  participants: [{ transport: "webrtc", identity: "browser-tab-1" }],
  metadata: { source: "sdk", session_id: "sess_123" },
});
python
call = rymi.calls.create(
    agent_id="550e8400-e29b-41d4-a716-446655440000",
    participants=[{"transport": "webrtc", "identity": "browser-tab-1"}],
    metadata={"source": "sdk", "session_id": "sess_123"},
)

Response 201 ​

json
{
  "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 ​

bash
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" }
  }'
ts
const call = await rymi.calls.create({
  agent_id: "550e8400-e29b-41d4-a716-446655440000",
  participants: [
    {
      transport: "pstn",
      identity: "+15551234567",
      from_number: "+15559876543",
    },
  ],
  metadata: { customer_name: "Alice" },
  variables: { customer_segment: "renewal" },
});
python
call = rymi.calls.create(
    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 ​

json
{
  "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:

bash
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": {
      "summary": { "enabled": true },
      "structured_extraction": {
        "json_schema": {
          "type": "object",
          "properties": {
            "booked_appointment": { "type": "boolean" },
            "preferred_date": { "type": "string" }
          }
        }
      },
      "evaluation": {
        "rubric": "1. Did the agent successfully book an appointment?"
      }
    }
  }'
ts
const call = await rymi.calls.create({
  agent_id: "550e8400-e29b-41d4-a716-446655440000",
  participants: [{ transport: "webrtc", identity: "browser-user" }],
  post_call: {
    summary: { enabled: true },
    structured_extraction: {
      json_schema: {
        type: "object",
        properties: {
          booked_appointment: { type: "boolean" },
          preferred_date: { type: "string" },
        },
      },
    },
    evaluation: {
      rubric: "1. Did the agent successfully book an appointment?",
    },
  },
});
python
call = rymi.calls.create(
    agent_id="550e8400-e29b-41d4-a716-446655440000",
    participants=[{"transport": "webrtc", "identity": "browser-user"}],
    post_call={
        "summary": {"enabled": True},
        "structured_extraction": {
            "json_schema": {
                "type": "object",
                "properties": {
                    "booked_appointment": {"type": "boolean"},
                    "preferred_date": {"type": "string"},
                },
            }
        },
        "evaluation": {
            "rubric": "1. 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 ​

StatusMeaning
400Validation error (missing agent_id, invalid participants, etc.)
400DNC conflict: one or more PSTN participants are on the Do-Not-Call list
400unsupported_country or invalid_phone_number: a phone number is outside Rymi's supported countries or doesn't parse
401Missing or invalid API key
402Insufficient credits
403Publishable key scope violation (e.g., phone channel not allowed)
404Agent not found for this tenant
409Agent is not publish-ready (code: agent_not_publish_ready): resolve publish validation blockers before starting live calls
422Provider key unavailable (code: provider_key_unavailable): the agent's LLM/STT/TTS provider key is not configured
423Agent is paused by an administrator (code: agent_admin_paused)
503Platform calls are disabled (code: platform_calls_disabled)

List Calls ​

GET/v1/calls

Returns a paginated list of call records for the authenticated tenant.

Query Parameters ​

ParameterTypeDefaultDescription
limitinteger200Max records to return (max 1000)
offsetinteger0Records to skip
cursorstring-Resume from a previous call ID when traversing call history
statusstring-Filter by call status: queued, ringing, in_progress, completed, failed, no_answer, busy, or canceled
agent_iduuid-Filter to calls for a single agent

Example Request ​

bash
curl "https://api.rymi.live/v1/calls?limit=50&status=completed" \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const { calls } = await rymi.calls.list({ limit: 50, status: "completed" });
python
result = rymi.calls.list(limit=50, status="completed")

Response 200 ​

json
{
  "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,
      "billable_seconds": 300,
      "total_cost": 0.30,
      "provider_cost": 0.18,
      "provider_cost_breakdown": { "llm": 0.05, "stt": 0.04, "tts": 0.09 },
      "provider_cost_calculated_at": "2026-03-01T10:05:10Z",
      "end_reason": "participant_disconnected",
      "metadata": { "batch_id": "batch_1710" },
      "intelligence_status": "completed",
      "sentiment": "positive",
      "participant_count": 1,
      "primary_participant": {
        "identity": "+15551234567",
        "transport": "pstn"
      },
      "participants": [
        { "id": "cp_1", "role": "caller", "transport": "pstn", "identity": "+15551234567", "status": "completed" }
      ]
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0,
  "next_cursor": null
}

sentiment is the post-call sentiment, null until post-call analysis finishes. The summary is on Call Detail.

end_reason (also on the Call Detail response) is an open string, not a closed enum. There is no database constraint on it, and PSTN calls report carrier-specific values. Treat unknown values gracefully rather than exhaustively matching.

Common values:

GroupValues
Clean endsparticipant_disconnected, client_disconnected, normal_hangup, natural_end, end_call_tool, agent_ended_call, completed
Limits and silencetime_limit_exceeded, max_call_duration, silence_timeout, silence_dead_air, demo_idle_timeout
Voicemailvoicemail_detected, voicemail_left
Failuresinsufficient_funds, no_provider_connected, room_setup_failed, room_connection_failed, session_init_failed, session_start_failed, worker_error, session_error, server_shutdown
Reaper backstopreaper_in_progress_timeout, reaper_post_dial_timeout, reaper_queued_timeout
Carrier (PSTN)<carrier>_<status>, e.g. twilio_completed, plivo_no-answer, vonage_rejected, telnyx_hangup

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot list call history

List Active Calls ​

GET/v1/calls/active

Returns the same payload shape as GET /v1/calls, filtered to calls with in_progress status.

Example Request ​

bash
curl https://api.rymi.live/v1/calls/active \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const { calls } = await rymi.calls.active();
python
result = rymi.calls.active()

Errors ​

StatusMeaning
401Missing or invalid API key

Add Participants ​

POST/v1/calls/:id/participants

Bring a browser participant into an existing PSTN call, or queue another PSTN leg on an active session.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Request Body ​

FieldTypeRequiredDescription
participantsParticipant[]YesOne or more participants to add

Example Request ​

bash
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" }
    ]
  }'
ts
const result = await rymi.calls.addParticipants("call_abc123", {
  participants: [{ transport: "webrtc", identity: "browser-tab-2" }],
});
python
result = rymi.calls.add_participants(
    "call_abc123",
    participants=[{"transport": "webrtc", "identity": "browser-tab-2"}],
)

Errors ​

StatusMeaning
400Invalid participant data
401Missing or invalid API key
403Publishable keys cannot add call participants, or the call does not belong to this tenant
404Call not found
409Agent is not publish-ready (code: agent_not_publish_ready)

Call Detail ​

GET/v1/calls/:id

Returns the expanded view of a call including participants, transcript, recording metadata, intelligence results, and event log.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Example Request ​

bash
curl https://api.rymi.live/v1/calls/call_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const call = await rymi.calls.retrieve("call_abc123");
python
call = rymi.calls.retrieve("call_abc123")

Response 200 ​

json
{
  "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": "completed",
    "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 ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot fetch call details
404Call not found

Call Summary ​

GET/v1/calls/:id/summary

Returns the persisted post-call summary and sentiment. It serves previously computed results and runs no LLM analysis at request time.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Example Request ​

bash
curl https://api.rymi.live/v1/calls/call_abc123/summary \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const summary = await rymi.calls.summary("call_abc123");
python
summary = rymi.calls.summary("call_abc123")

Response 200 ​

json
{
  "status": "completed",
  "sentiment": "positive",
  "summary": "The caller confirmed the appointment and no follow-up was needed."
}

Errors ​

StatusMeaning
401Missing or invalid API key
404Call not found or summary not yet available

Call Transcript ​

GET/v1/calls/:id/transcript

Returns the raw and normalized transcript for a completed call.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Example Request ​

bash
curl https://api.rymi.live/v1/calls/call_abc123/transcript \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const transcript = await rymi.calls.transcript("call_abc123");
python
transcript = rymi.calls.transcript("call_abc123")

Response 200 ​

json
{
  "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 ​

FieldTypeDescription
speakerstringuser or agent
textstringTranscribed text
sequenceintegerZero-based segment order
started_at_msintegerSegment start time in milliseconds from call start
ended_at_msintegerSegment end time in milliseconds from call start
is_finalbooleanWhether this is a final (non-interim) transcript segment
sourcestringTranscript source (e.g., runtime)

Errors ​

StatusMeaning
401Missing or invalid API key
404Call not found or transcript not yet available

Call Recording ​

GET/v1/calls/:id/recording

Returns the latest recording metadata plus time-limited signed URLs for audio download.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Example Request ​

bash
curl https://api.rymi.live/v1/calls/call_abc123/recording \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const recording = await rymi.calls.recording("call_abc123");
python
recording = rymi.calls.recording("call_abc123")

Response 200 ​

json
{
  "call_id": "call_abc123",
  "recording": {
    "id": "rec_1",
    "status": "completed",
    "format": "wav",
    "provider_recording_id": "prov_123",
    "metadata": {
      "stereo_mix": {
        "signed_url": "https://storage.rymi.live/recordings/..."
      }
    }
  }
}

Recording Status Values ​

StatusDescription
processingRecording is being captured or finalized (initial state)
completedRecording is available for download
failedRecording processing failed

When recording is not enabled for a call, no recording record exists and the endpoint returns 404.

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot access recordings
404Call not found or recording not available

End a Call ​

POST/v1/calls/:id/end

Force-ends an active call by closing the LiveKit room. The call transitions to completed and post-call processing is triggered.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Example Request ​

bash
curl -X POST https://api.rymi.live/v1/calls/call_abc123/end \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const result = await rymi.calls.end("call_abc123");
python
result = rymi.calls.end("call_abc123")

Response 200 ​

json
{
  "status": "ended",
  "id": "call_abc123",
  "message": "Call has been terminated."
}

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot end calls
404Call not found
409Call is already completed or failed

Call Events ​

GET/v1/calls/:id/events

Returns the event log for a specific call, including lifecycle transitions and post-call processing events. Use it to build real-time dashboards and debug call flows.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Query Parameters ​

ParameterTypeDefaultDescription
limitinteger50Max records to return (max 200)
offsetinteger0Records to skip

Example Request ​

bash
curl "https://api.rymi.live/v1/calls/call_abc123/events?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200 ​

json
{
  "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 ​

FieldTypeDescription
idstringEvent ID
call_idstringAssociated call ID
levelstringinfo, warning, or error
sourcestringEvent source: lifecycle, post_call, telephony, livekit
messagestringHuman-readable event description
created_atstringISO 8601 timestamp

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot access call events
404Call not found

Reprocess Post-call Intelligence ​

POST/v1/calls/:id/reprocess

Queues post-call intelligence again for a call. Run it after you change the agent's extraction schema or evaluation criteria and want fresh analysis.

Path Parameters ​

ParameterTypeDescription
iduuidCall ID

Example Request ​

bash
curl -X POST https://api.rymi.live/v1/calls/call_abc123/reprocess \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const result = await rymi.calls.reprocess("call_abc123");
python
result = rymi.calls.reprocess("call_abc123")

Response 202 ​

json
{
  "status": "queued",
  "job_id": "job_123",
  "message": "Post-call intelligence reprocessing has been queued."
}

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot trigger reprocessing
404Call not found
409Post-call intelligence is already being processed for this call

Queue Stats ​

GET/v1/calls/queue/stats

Returns the outbound dialing queue counts for PSTN calls.

Example Request ​

bash
curl https://api.rymi.live/v1/calls/queue/stats \
  -H "Authorization: Bearer YOUR_API_KEY"
ts
const stats = await rymi.calls.queueStats();
python
stats = rymi.calls.queue_stats()

Response 200 ​

json
{
  "waiting": 12,
  "active": 2,
  "completed": 340,
  "failed": 4
}

List Scheduled Callbacks ​

GET/v1/scheduled-callbacks

Returns the callbacks your agents scheduled for themselves with the Scheduled callbacks tool, latest due time first. The platform places each one at its due time. There is no SDK or MCP wrapper for this endpoint yet.

Query Parameters ​

ParameterTypeRequiredDefaultDescription
agent_idstringNo-Only callbacks scheduled by this agent
statusstringNo-One of pending, dispatching, placed, no_answer_retry, done, cancelled, failed
limitintegerNo501 to 200
offsetintegerNo0Rows to skip

Example Request ​

bash
curl "https://api.rymi.live/v1/scheduled-callbacks?status=pending&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200 ​

json
{
  "callbacks": [
    {
      "id": "6c1f5e0a-2b7d-4c0e-9a61-3d2f8b4e7a10",
      "agent_id": "16e0724d-bc5e-4a82-9792-f3ac83c561f0",
      "agent_name": "Isha",
      "to_number": "+919876543210",
      "due_at": "2026-10-06T12:30:00+00:00",
      "status": "pending",
      "reason": "driving, wants callback",
      "notes": "Rohit, budget 50 lakh, Skyline Greens",
      "attempts": 0,
      "result_call_id": null,
      "last_error": null,
      "created_at": "2026-10-05T10:00:00+00:00"
    }
  ],
  "total": 1,
  "offset": 0,
  "limit": 50
}
FieldDescription
due_atWhen the call is due, in UTC. 2026-10-06T12:30:00+00:00 is 6:00 pm IST
statusSee the statuses in the guide
attemptsCalls placed so far (0, 1 or 2)
result_call_idThe call that was placed, once there is one. Fetch it with Call Detail
last_errorWhy it did not go out: no_caller_id, dnc, dnc_lookup_failed, no_answer, busy, or cancelled by user

Errors ​

StatusMeaning
400status is not one of the listed values
401Missing or invalid API key
403Publishable keys cannot read scheduled callbacks

Cancel a Scheduled Callback ​

POST/v1/scheduled-callbacks/:id/cancel

Stops a callback that has not been placed yet. It works while the status is pending or no_answer_retry.

Example Request ​

bash
curl -X POST https://api.rymi.live/v1/scheduled-callbacks/6c1f5e0a-2b7d-4c0e-9a61-3d2f8b4e7a10/cancel \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200 ​

json
{ "status": "cancelled", "id": "6c1f5e0a-2b7d-4c0e-9a61-3d2f8b4e7a10" }

Errors ​

StatusMeaning
401Missing or invalid API key
403Publishable keys cannot cancel scheduled callbacks
404No callback with that id in your workspace
409The callback is already being placed or has finished, so it cannot be cancelled

Publishable Key Rules ​

When using a publishable key (sb_publishable_...) to create calls:

  • WebRTC: Allowed when the key permits the web channel.
  • PSTN: Allowed only when the key permits the phone channel.
  • Phone limit: Publishable phone calls must target exactly one PSTN participant and cannot override agent_id or from_number.
  • Read restrictions: Publishable keys cannot list call history, fetch recordings, access transcripts, or trigger reprocessing.