ErzyCall API
    ErzyCall API

    Getting Started

    Quick StartAuthentication

    Guides

    Rate LimitingError HandlingWebhooks

    API Reference

    CallsContactsCasesAssistantsPhone NumbersContact GroupsWebhook EndpointsWhatsApp

    Calls

    List, create, view, and cancel voice calls.

    The Call Object

    Every calls endpoint returns call objects with the following fields:

    FieldTypeDescription
    idstringUnique call ID. Use it with GET /calls/{id}.
    statusstringnew, scheduled, processing, ended, cancelled, error
    directionstringoutbound — your assistant placed the call. inbound — someone called your number.
    callFromstringYour organization's phone number
    callTostringThe other party: the person called (outbound) or the caller (inbound)
    caseIdstring | nullCase used as the call script
    contactIdstring | nullLinked contact
    firstMessagestring | nullThe assistant's opening message
    apiCallIdstring | nullVoice-platform call ID, set once the call starts
    apiCallStatusstring | nullLive platform status: queued, ringing, in-progress, ended, forwarding
    endedReasonstring | nullWhy the call ended, e.g. customer-ended-call, assistant-ended-call, voicemail-reached
    resultStatusstring | nullAI analysis verdict: Answered, Voicemail, Not Answered
    recordingUrlstring | nullAudio recording of the call
    durationSecondsnumber | nullCall length in seconds, null until the call has ended
    variableValuesobject | nullVariables injected into the call
    createdAt, updatedAtstringISO 8601 timestamps

    GET /calls/{id} additionally returns a transcript array — see Get Call.

    List Calls

    Retrieve a paginated list of calls for your organization — both outbound and inbound. Use each call's direction field to tell them apart.

    GET /api/v1/calls

    Required scope: calls:read

    Query Parameters

    ParameterTypeDefaultDescription
    limitinteger25Results per page (1–100)
    cursorstring—Pagination cursor from a previous response
    statusstring—Filter by status: new, scheduled, processing, ended, cancelled, error
    contactIdstring—Filter by contact ID
    caseIdstring—Filter by case ID
    fromstring—ISO 8601 datetime — only calls after this time
    tostring—ISO 8601 datetime — only calls before this time

    Example Request

    curl -X GET "https://app.erzycall.com/api/v1/calls?limit=10&status=ended" \
      -H "X-API-Key: ek_live_abc123"

    Example Response

    {
      "data": [
        {
          "id": "jd7bk3xw9q2m5n8p1r4t6v0y2c",
          "status": "ended",
          "direction": "outbound",
          "callTo": "+14155551234",
          "callFrom": "+14155559999",
          "caseId": "case_789",
          "contactId": "contact_456",
          "firstMessage": "Hi, this is a follow-up call regarding your inquiry.",
          "apiCallId": "019c1b2e-8f3a-4c5d-9e6f-7a8b9c0d1e2f",
          "apiCallStatus": "ended",
          "endedReason": "customer-ended-call",
          "resultStatus": "Answered",
          "recordingUrl": "https://storage.example.com/recordings/019c1b2e.wav",
          "durationSeconds": 45,
          "variableValues": { "name": "Ahmad" },
          "createdAt": "2025-01-15T10:30:00.000Z",
          "updatedAt": "2025-01-15T10:31:02.000Z"
        }
      ],
      "pagination": {
        "cursor": "eyJwb3...",
        "hasMore": true,
        "pageSize": 10
      }
    }

    Create Call

    Trigger a new outbound call or schedule one for later.

    POST /api/v1/calls

    Required scope: calls:write

    Request Body

    FieldTypeRequiredDescription
    tostringYesDestination phone number in E.164 format (e.g., +14155551234)
    fromstringYesCaller ID — must be a phone number assigned to your organization
    contactIdstringNoAssociate with an existing contact. Also enables variable resolution — {{name}}, {{email}}, {{phone}}, and {{notes}} are automatically populated from the contact record.
    caseIdstringNoUse an existing case as the call script. The case provides the first message, system prompt, tools, and variable definitions. See Using Cases below.
    firstMessagestringNoOpening message for the AI assistant (max 1,000 chars). Overrides the case's first message if both are provided.
    scheduledAtstringNoISO 8601 datetime to schedule the call for later. Omit for an immediate call.
    variableValuesobjectNoKey-value pairs to inject into the first message and system prompt. Variables use {{variableName}} syntax in templates.

    Using Cases with Calls

    A case is a reusable call script that defines the AI assistant's first message, system prompt (personality, instructions, conversation flow), tools (e.g., calendar booking), and variable definitions. When you pass a caseId, the assistant follows the case structure automatically.

    The priority for firstMessage and system prompt is: caller-supplied → case → generic default.

    ScenarioFirst MessageSystem PromptToolsBest For
    caseId only✅ From case✅ From case✅ From caseStandard scripted calls — the AI follows the full case flow
    firstMessage only✅ Your message⚠️ Generic default❌ NoneSimple one-liner calls with no conversation structure
    Both caseId + firstMessage✅ Your message (overrides case)✅ From case✅ From caseScripted calls with a custom opener per contact
    Neither⚠️ Generic default⚠️ Generic default❌ NoneNot recommended — results in a bare assistant

    Tip: For most use cases, pass a caseId and let the case handle everything. Use firstMessage only when you need a custom opener that differs from the case template.

    Variable Resolution

    Variables in the case's first message and system prompt (e.g., {{name}}, {{email}}) are resolved automatically from multiple sources:

    1. variableValues you pass in the request body (highest priority)
    2. Contact data from the contactId — maps {{name}} → contact title, {{email}} → contact email, etc.
    3. Case variable defaults defined in the case configuration

    For example, if your case's first message is "Hello, is this {{name}}?" and you pass a contactId for "Artur Temirov", the AI will say: "Hello, is this Artur Temirov?"

    Example: Call with Case

    curl -X POST "https://app.erzycall.com/api/v1/calls" \
      -H "X-API-Key: ek_live_abc123" \
      -H "Content-Type: application/json" \
      -d '{
        "to": "+60111234567",
        "from": "+60360431879",
        "caseId": "case_789",
        "contactId": "contact_456",
        "variableValues": {
          "name": "Ahmad",
          "company": "TechCorp"
        }
      }'

    Example: Simple Call (No Case)

    curl -X POST "https://app.erzycall.com/api/v1/calls" \
      -H "X-API-Key: ek_live_abc123" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: unique-call-12345" \
      -d '{
        "to": "+14155551234",
        "from": "+14155559999",
        "firstMessage": "Hi, this is a follow-up call regarding your inquiry.",
        "contactId": "contact_456"
      }'

    Example: Scheduled Call

    curl -X POST "https://app.erzycall.com/api/v1/calls" \
      -H "X-API-Key: ek_live_abc123" \
      -H "Content-Type: application/json" \
      -d '{
        "to": "+60111234567",
        "from": "+60360431879",
        "caseId": "case_789",
        "contactId": "contact_456",
        "scheduledAt": "2025-01-16T14:00:00.000Z"
      }'

    Example Response (201 Created)

    {
      "data": {
        "id": "jd7bk3xw9q2m5n8p1r4t6v0y2c",
        "status": "new",
        "direction": "outbound",
        "callTo": "+14155551234",
        "callFrom": "+14155559999",
        "caseId": "case_789",
        "contactId": "contact_456",
        "firstMessage": null,
        "apiCallId": null,
        "apiCallStatus": null,
        "endedReason": null,
        "resultStatus": null,
        "recordingUrl": null,
        "durationSeconds": null,
        "variableValues": { "name": "Ahmad", "company": "TechCorp" },
        "createdAt": "2025-01-15T10:30:00.000Z",
        "updatedAt": "2025-01-15T10:30:00.000Z"
      }
    }

    apiCallId, recordingUrl, durationSeconds, and the other result fields are null until the call is picked up and completed — poll GET /calls/{id} or subscribe to webhooks for updates.

    Immediate calls have status new and are picked up by the system within ~60 seconds. Scheduled calls have status scheduled and fire at the specified scheduledAt time.

    Errors

    StatusCodeDescription
    422INVALID_PHONEThe from number is not assigned to your organization
    404NOT_FOUNDReferenced contactId or caseId not found

    Get Call

    Retrieve details for a single call, including the full conversation transcript.

    GET /api/v1/calls/{id}

    Required scope: calls:read

    Example Request

    curl -X GET "https://app.erzycall.com/api/v1/calls/jd7bk3xw9q2m5n8p1r4t6v0y2c" \
      -H "X-API-Key: ek_live_abc123"

    Example Response

    The example below is an inbound call: callFrom is the organization's number and callTo is the person who called it.

    {
      "data": {
        "id": "jd7bk3xw9q2m5n8p1r4t6v0y2c",
        "status": "ended",
        "direction": "inbound",
        "callTo": "+60111234567",
        "callFrom": "+60360431879",
        "caseId": null,
        "contactId": "contact_456",
        "firstMessage": null,
        "apiCallId": "019c1b2e-8f3a-4c5d-9e6f-7a8b9c0d1e2f",
        "apiCallStatus": "ended",
        "endedReason": "customer-ended-call",
        "resultStatus": "Answered",
        "recordingUrl": "https://storage.example.com/recordings/019c1b2e.wav",
        "durationSeconds": 47,
        "variableValues": null,
        "createdAt": "2025-01-15T10:30:00.000Z",
        "updatedAt": "2025-01-15T10:31:02.000Z",
        "transcript": [
          {
            "role": "assistant",
            "content": "Hello! Thanks for calling. How can I help you today?",
            "timestamp": 1736937000000
          },
          {
            "role": "user",
            "content": "Hi, I'd like to book an appointment for tomorrow morning.",
            "timestamp": 1736937004500
          },
          {
            "role": "assistant",
            "content": "Of course — let me check tomorrow's availability.",
            "timestamp": 1736937008200
          }
        ]
      }
    }

    Transcript

    transcript is an array of conversation messages in order:

    FieldTypeDescription
    rolestringassistant (your AI), user (the other party), or system
    contentstringWhat was said
    timestampnumber | nullEpoch milliseconds, when available

    The transcript fills in while the call is in progress and is complete once status is ended. Calls that never connected (e.g. Not Answered) return an empty array.


    Cancel Call

    Cancel a scheduled or pending call. Only calls with status new or scheduled can be cancelled.

    DELETE /api/v1/calls/{id}

    Required scope: calls:write

    Example Request

    curl -X DELETE "https://app.erzycall.com/api/v1/calls/abc123" \
      -H "X-API-Key: ek_live_abc123"

    Response

    Returns 204 No Content on success.

    Errors

    StatusCodeDescription
    404NOT_FOUNDCall not found
    422INVALID_STATECall cannot be cancelled in its current status (e.g., already ended)

    Webhooks

    Receive real-time event notifications via webhooks.

    Contacts

    Create, read, update, delete, and search contacts.

    On this page

    The Call ObjectList CallsQuery ParametersExample RequestExample ResponseCreate CallRequest BodyUsing Cases with CallsVariable ResolutionExample: Call with CaseExample: Simple Call (No Case)Example: Scheduled CallExample Response (201 Created)ErrorsGet CallExample RequestExample ResponseTranscriptCancel CallExample RequestResponseErrors