> ## Documentation Index
> Fetch the complete documentation index at: https://docs.miraiminds.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Get call

> The call record. `status` moves `queued → dialing → in_progress`, then lands on one final value: `completed`, `voicemail`, `no_answer`, `busy`, `failed`, `timeout` or `aborted`. A final status never changes. `ended_reason` says why it ended.

`cost` is settled when the call ends. Only calls that connected are billed. `analysis` appears once the post-call analysis has settled (see [Get call analysis](/api-reference/calls/get-call-analysis)), and a call run by a node-based agent also carries `flow`.

Webhooks are the better way to follow a call. If you poll, poll every 5 seconds at most. A call id from another workspace is a 404, the same as one that never existed.



## OpenAPI

````yaml /api-reference/openapi.json get /v2/calls/{call_id}
openapi: 3.1.0
info:
  title: Mirai Voice API
  version: 2026-10-15.analysis-templates
  description: >-
    The v2 API for voice agents, calls, campaigns, phone numbers and speech.
    Every request carries `Authorization: Bearer sk_live_…`. Generated from the
    API's own contract and its Postman collection.
servers:
  - url: https://sandbox.voice.miraiminds.co
    description: 'Sandbox: trial workspaces, before your company goes live'
  - url: https://prod.voice.miraiminds.co
    description: 'Production: workspaces that have gone live'
security:
  - bearerAuth: []
tags:
  - name: Agents
    description: >-
      An agent is what a call runs: its prompt (or a node flow, see the Flows
      section), voice, language and limits. Write it once and dial it as often
      as you like; each call fills in its own `variables`.


      Every save creates a new revision. You can read old revisions, roll back
      to one, and publish a draft when it is ready. None of the requests here
      place a call or charge your wallet.
  - name: Calls
    description: >-
      Place a call, follow it while it runs, then read what happened: the
      transcript, the recording, the post-call analysis.


      `POST /v2/calls` answers before the phone rings, with an id. Everything
      after that is about that id. Live control and the live event stream work
      on browser calls (`channel: "web"`) and realtime sessions only; a phone
      call answers them with `400 unsupported_channel`.
  - name: Flows
    description: >-
      A node-based agent runs the call as a graph of steps. Each node has its
      own instructions, and the agent moves to the next node when a transition's
      condition is met, so a call with branches (wrong person, not now,
      reschedule) stays easy to follow and to change.


      The usual path: draft a graph from a brief or from recordings of your real
      calls, check it, test it with simulated calls, then save it on an agent.
      Drafting, transcribing and testing use AI models and charge your wallet;
      checking, saving and reading are free.


      Full guide: https://docs.miraiminds.co/v2/node-agents
  - name: Tools and secrets
    description: >-
      Connect your own APIs to an agent. A tool runs at one of three moments:


      * `pre_call`, before dialling: fetch context for the greeting, or skip the
      call.

      * `on_call`, when the agent decides to use it mid-conversation: look
      something up, book something.

      * `post_call`, after the call has settled: send the outcome to your CRM,
      schedule a call back.


      The order here is the order you'd use them in: see what's available, store
      your credential as a secret, add a tool, test it against your endpoint,
      then read each call's tool runs. Tools themselves cost nothing extra.


      Tool definitions use Mirai's own templates, like `{{ args.date }}` and `{{
      secrets.crm_key }}`.


      A definition that doesn't validate comes back as a list, so you can fix
      everything at once: `{"error": "invalid_tools", "details": [{"path",
      "message"}]}`. Everything else uses the usual `{"error": {"code",
      "message"}}`.
  - name: Campaigns
    description: >-
      Call a whole list with one agent. Upload contacts, say which days and
      hours the campaign may ring, and start it. From then on it dials by
      itself: it paces itself, waits overnight, retries calls that didn't
      connect, skips numbers on your do-not-call list, and pauses itself when
      its budget or your wallet runs out.


      Campaign calls are ordinary calls. They show up in `GET /v2/calls`, send
      the same `call.*` webhooks and bill the same per-minute rate. In a sandbox
      workspace every campaign runs and bills at T5 (₹5 a minute), whatever tier
      you ask for.


      Money on a campaign is in **paise**: `"budget_paise": 50000` is ₹500.


      The requests run top to bottom: create saves `campaign_id`, and the rest
      use it. Starting a campaign rings every contact on it, so put numbers
      you're allowed to call in the bodies first.
  - name: Do-not-call list
    description: >-
      Numbers your campaigns will never dial. The list covers every campaign in
      the workspace, including ones that are already running: it's checked at
      the moment a contact is about to be called, so a number added mid-campaign
      is skipped from then on. A skipped contact stays in its campaign as
      `suppressed` and costs nothing.


      It doesn't apply to single calls placed with `POST /v2/calls`; check the
      list yourself before those if you need to. It's your own list, not the
      national DND register, and adding a number here doesn't meet your DND
      obligations.
  - name: Phone numbers
    description: >-
      The numbers your agents answer. Each one comes from the **Telephony**
      section:


      * **Rented from Mirai.** Once the rental is active, the number shows up
      here by itself (`ownership: managed`).

      * **From your own Plivo account.** Connect the account in Telephony, list
      its numbers, then bring one here with [Import a Plivo
      number](/api-reference/phone-numbers/import-a-plivo-number) (`ownership:
      customer`). Plivo keeps billing you for it.


      After that it's two steps, in this order: [Assign an
      agent](/api-reference/phone-numbers/assign-an-agent) (who answers), then
      [Turn on incoming
      calls](/api-reference/phone-numbers/turn-on-incoming-calls). `state` is
      `imported` until calls are on and `ready` after; `error` means the last
      attempt to turn calls on failed, and `setup_error` says why.


      Every change sends the number's current `version`, and each change raises
      it by one. If you're not sure what it is, read the number first; a stale
      version is a 409 `conflict` and changes nothing.


      To call out from one of your numbers, place a call with `phone_number_id`
      set to its id once it is `ready` (Indian destinations only). Calls on your
      numbers are billed like any other call.


      Every number also says how it is doing in `health`: `state` is `active`,
      `warming` (its first week, at half its pool's pace), `resting`, `cooling`
      (rested three times in a day; waits for you) or `retired`, with this
      hour's attempts and seven days of answers. You can rest, resume and retire
      your own numbers; a resting or retired number still answers calls to it.
  - name: Phone pools
    description: >-
      A pool is a group of your own phone numbers that a campaign, an agent or a
      single call can ring from. Each call takes the number best placed for it:
      a number a contact has already been rung from stays theirs on a retry,
      numbers in the contact's own circle come first, and the pool's pace
      (`max_per_hour`, per number) is held across every campaign and API call at
      once. A number whose answers drop well below its pool-mates' rests on its
      own for 45 minutes.


      Point a campaign at a pool with `pool_id` on [Create a
      campaign](/api-reference/campaigns/create-a-campaign), an agent with
      `calls_from: {"pool_id": …}`, or one call with `pool_id` on [Place a
      call](/api-reference/calls/place-a-call). `pool_id` and `phone_number_id`
      never go together. With nothing chosen, calls come from the agent's
      setting, then the pool marked `default_for_campaigns`, then the Mirai
      shared line. A call's `calls_from_source` is `pool` (with `pool_id`) when
      a pool picked its number.


      A single call on a pool whose numbers are all resting or at their pace
      this hour answers 409 `pool_busy` with `Retry-After`; one with no number
      that can call, 409 `pool_unavailable`. A campaign doesn't fail: it waits
      and carries on.


      `purpose` is what the calls are for: `outreach` (promotional),
      `reminders`, `support` or `other`. It sets the starting pace: 40 an hour
      for support, 60 otherwise. Pools are free; numbers are billed as numbers.
  - name: Telephony
    description: >-
      Getting a phone number for your agent. There are two ways, and a workspace
      can use both.


      **1. Rent a number from Mirai.** ₹500 a month, paid as ₹1,500 from your
      wallet every three months, renewing until you turn it off. Indian numbers
      need a business verification that Plivo approves once: read the
      requirements, submit your details and documents, then refresh until it's
      `accepted`. After that: search, quote, rent. The rented number appears in
      **Phone numbers** by itself.


      **2. Connect your own Plivo account.** Plivo keeps billing you directly.
      Connect it with your Auth ID and Auth Token, list the numbers it owns, and
      bring one over with [Import a Plivo
      number](/api-reference/phone-numbers/import-a-plivo-number). A Plivo main
      account can also rent new numbers through the same search → quote → rent
      requests, with its connection id as `account`.


      Either way you finish in **Phone numbers**: assign the agent that answers,
      then turn on incoming calls.


      The last two requests verify your own phone, so the workspace can ring it
      from Mirai's shared test number (test calls are placed from the Numbers
      page in the console).


      Indian (+91) numbers only for now. If phone numbers aren't available on
      the host you're calling, every request here answers 503
      `telephony_unavailable`.
  - name: Transcriptions
    description: >-
      Turn a recorded call (or any recording) into a transcript with speakers
      and timestamps. Hindi, English, Gujarati and mixed speech are written the
      way they were spoken, never translated. ₹18 per hour of audio; failed and
      degraded jobs are free.
  - name: Speech to text
    description: >-
      Speech to text in ten languages, two ways: send one recording and get its
      text back in the same request ([Transcribe a
      recording](/api-reference/speech-to-text/transcribe-a-recording)), or
      stream live audio over one WebSocket per call and read partial transcripts
      while people speak, then one final transcript per utterance. Language
      codes: hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or
      ml-IN.


      `wss://sandbox.voice.miraiminds.co/v1/audio/transcriptions/stream?language_code=hi-IN&encoding=mulaw&sample_rate=8000&endpointing=manual`


      (`wss://prod.voice.miraiminds.co` once your company has gone live), with
      the header `Authorization: Bearer sk_live_YOUR_API_KEY`. 8 or 16 kHz,
      16-bit PCM, μ-law or A-law. A browser uses `?token=` from [Mint stream
      tokens](/api-reference/speech-to-text/mint-stream-tokens) instead, because
      it cannot set headers on a WebSocket.


      Send JSON text frames: `{"event": "speech_start"}`, then `{"event":
      "audio_input", "audio": "<base64 audio>"}` as the audio arrives, then
      `{"event": "speech_end"}`; `{"event": "end"}` closes the session. You
      receive `session.begin` first, `transcript.partial` while an utterance is
      open, exactly one `transcript.final` per utterance, and `session.end` with
      `audio_seconds_billed` and `cost_paise`.


      Every event, both endpointing modes, limits and errors:
      https://docs.miraiminds.co/v2/stt-quickstart
  - name: Text to speech
    description: >-
      Turn text into speech in one request, and read back what each request
      cost.
  - name: Wallet
    description: >-
      Your prepaid balance and every line that moved it. Calls, text to speech,
      flow drafts, transcriptions and number rentals all debit the same wallet.
  - name: Reference
    description: The voice catalogue, and the API contract as a machine-readable document.
paths:
  /v2/calls/{call_id}:
    get:
      tags:
        - Calls
      summary: Get call
      description: >-
        The call record. `status` moves `queued → dialing → in_progress`, then
        lands on one final value: `completed`, `voicemail`, `no_answer`, `busy`,
        `failed`, `timeout` or `aborted`. A final status never changes.
        `ended_reason` says why it ended.


        `cost` is settled when the call ends. Only calls that connected are
        billed. `analysis` appears once the post-call analysis has settled (see
        [Get call analysis](/api-reference/calls/get-call-analysis)), and a call
        run by a node-based agent also carries `flow`.


        Webhooks are the better way to follow a call. If you poll, poll every 5
        seconds at most. A call id from another workspace is a 404, the same as
        one that never existed.
      operationId: get_call
      parameters:
        - name: call_id
          in: path
          required: true
          description: The call's id (`call_…`), from the `202` that created it.
          schema:
            type: string
          example: call_01K2M4RB8CDEFGHJKMNPQRST
      responses:
        '200':
          description: A finished call
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Call'
              examples:
                A finished call:
                  summary: 200 — a finished call
                  value:
                    id: call_01K2M4RB8CDEFGHJKMNPQRST
                    object: call
                    agent_id: agt_01K2M4P7QRSTVWXYZ0A1B2C3
                    agent_revision: 4
                    to: '+919876543210'
                    route: trunk
                    direction: outbound
                    channel: phone
                    tier: t5
                    status: completed
                    ended_reason: assistant-ended-call
                    created_at: '2026-10-09T09:15:12.408913574Z'
                    started_at: '2026-10-09T09:15:19Z'
                    ended_at: '2026-10-09T09:16:55Z'
                    duration_secs: 96
                    cost:
                      amount_inr: 8.33
                      per_min_inr: 5
                      billing_block_secs: 10
                      voice_per_min_inr: 5
                    cost_inr: 8.33
                    variables:
                      name: राहुल
                      vehicle: स्विफ्ट
                      due_date: 18 अक्टूबर
                      customer_id: cus_42
                    max_duration_secs: 300
                    metadata:
                      reminder_id: rem_8842
                    recording_available: true
                    transcript_available: true
                    transcript_status: ready
                    analysis:
                      status: done
                      state: completed
                      generation: 1
                      agent_revision: 4
                      completed_at: '2026-10-09T09:17:08Z'
                      summary: >-
                        Rahul agreed to service his Swift on 18 October and
                        booked the 10:30 slot. No follow-up needed.
                      success: true
                      data:
                        service_booked: true
                        preferred_date: '2026-10-18'
                        callback_needed: false
                Still ringing:
                  summary: 200 — still ringing
                  value:
                    id: call_01K2M4RB8CDEFGHJKMNPQRST
                    object: call
                    agent_id: agt_01K2M4P7QRSTVWXYZ0A1B2C3
                    agent_revision: 4
                    to: '+919876543210'
                    route: trunk
                    direction: outbound
                    channel: phone
                    tier: t5
                    status: dialing
                    ended_reason: null
                    created_at: '2026-10-09T09:15:12.408913574Z'
                    started_at: null
                    ended_at: null
                    duration_secs: 0
                    cost:
                      amount_inr: 0
                      per_min_inr: 5
                      billing_block_secs: 10
                      voice_per_min_inr: 5
                    cost_inr: null
                    variables:
                      name: राहुल
                      vehicle: स्विफ्ट
                      due_date: 18 अक्टूबर
                      customer_id: cus_42
                    max_duration_secs: 300
                    metadata:
                      reminder_id: rem_8842
                    recording_available: false
                    transcript_available: false
                    transcript_status: pending
                    analysis: null
        '404':
          description: No such call
          content:
            application/json:
              examples:
                No such call:
                  summary: 404 — no such call
                  value:
                    error:
                      code: not_found
                      message: no call call_01K2M4RB8CDEFGHJKMNPQRST
components:
  schemas:
    Call:
      description: >-
        Partial call response schema documenting additive fields; other existing
        call fields are retained.
      properties:
        analysis:
          $ref: '#/components/schemas/CallAnalysisValue'
        calls_from_source:
          description: >-
            How an outbound phone call's number was chosen: request (the call's
            own phone_number_id, or its campaign's), agent (the agent's
            calls_from), shared (the Mirai shared line, shared with other
            customers and showing as Mirai) or trunk (a carrier line from a
            campaign's caller_ids). Absent on inbound, web and WhatsApp calls.
          enum:
            - request
            - agent
            - shared
            - trunk
          type: string
        campaign_id:
          description: >-
            The campaign that placed the call. Present on every view and event
            of a campaign call; absent on every other call.
          type: string
        channel:
          description: >-
            How the call was held: phone (dialled out, answered inbound, or a
            WhatsApp call), web (a browser session), text (the console's typed
            test chat) or realtime (a Realtime API session). The same vocabulary
            as GET /v2/calls/summary's by_channel. Present wherever created_at
            is.
          enum:
            - phone
            - web
            - text
            - realtime
          type: string
        contact_id:
          description: >-
            The campaign contact the call was to: the id you sent with the
            contact, or the one minted for it. Present wherever campaign_id is.
          type: string
        created_at:
          description: >-
            When the call was accepted (RFC 3339, UTC): the time GET /v2/calls
            orders by and its from/to filter on. Present on GET and list, and in
            data.call of the ending event (call.completed, call.failed,
            call.voicemail, call.aborted) and call.processed; not on call.queued
            or call.started. Absent only on a call stored without one.
          format: date-time
          type: string
        flow:
          $ref: '#/components/schemas/CallFlow'
        from:
          description: >-
            Phone calls only. The number the call rang from: your phone number
            (phone_number_id), the campaign's caller ID, or the shared line the
            call was dialled through. Present once the call has been dialled,
            and on every event from call.started on; absent on web and realtime
            calls.
          type: string
        id:
          type: string
        metadata:
          additionalProperties:
            maxLength: 256
            type: string
          description: >-
            The metadata sent when the call was created — or, for a campaign
            call, the contact's metadata — echoed unchanged here and in every
            webhook's data.call. Never given to the agent. Absent when the call
            has none.
          maxProperties: 16
          propertyNames:
            pattern: ^[A-Za-z0-9_][A-Za-z0-9_.:-]{0,39}$
          type: object
        phone_number_id:
          description: >-
            The id of your phone number the call rang from or was answered on.
            Absent when it rang from the shared line.
          type: string
        transcript_status:
          description: >-
            pending until the call has ended and its transcript is settled;
            ready when GET /v2/calls/{id}/transcript returns turns; empty when
            nobody spoke or media never started; failed when the transcript was
            lost. Present on GET and list.
          enum:
            - pending
            - ready
            - empty
            - failed
          type: string
      type: object
    CallAnalysisValue:
      description: >-
        Analysis embedded on a call and in result/processed events. status
        preserves the legacy processing state; durable extraction adds state,
        generation and agent_revision when available. success is explicitly null
        when unknown.
      properties:
        agent_revision:
          type: integer
        completed_at:
          format: date-time
          type: string
        data:
          additionalProperties: true
          type: object
        error:
          properties:
            code:
              type: string
            message:
              type: string
          type: object
        generation:
          minimum: 1
          type: integer
        state:
          enum:
            - waiting_for_call
            - pending
            - processing
            - completed
            - failed
            - skipped
            - unavailable
          type: string
        status:
          description: >-
            Legacy processing status, preserved alongside durable extraction
            state.
          type: string
        success:
          type:
            - boolean
            - 'null'
        summary:
          type: string
        template:
          $ref: '#/components/schemas/AnalysisTemplateResult'
      required:
        - status
        - success
      type: object
    CallFlow:
      description: >-
        A flow agent's call outcome. Present on GET /v2/calls/{id}, GET
        /v2/calls and call.processed data.call once the call's flow report has
        arrived (normally within seconds of the call ending); absent before that
        and on every prompt agent's call.
      properties:
        final_node:
          description: >-
            Id of the node the call ended on. Absent when the flow never entered
            a node (for example, the call failed before media).
          type: string
        nodes_visited:
          description: Node names in the order each was first entered; [] when none.
          items:
            type: string
          maxItems: 100
          type: array
        status:
          description: >-
            How the flow ended: end_call (an endCall node was reached),
            user_hangup, user_idle_max_duration_exceeded,
            call_duration_exceeded, pipeline_error, voicemail_detected or
            system_cancelled. A value outside this list is passed through as
            sent; treat it as an ending you do not recognise. Absent while only
            a partial report has arrived.
          examples:
            - end_call
            - user_hangup
            - user_idle_max_duration_exceeded
            - call_duration_exceeded
            - pipeline_error
            - voicemail_detected
            - system_cancelled
          type: string
        tags:
          description: >-
            Call tags the flow recorded (the disposition, user_speech, tag_*
            extractions). Absent when there are none.
          items:
            type: string
          maxItems: 100
          type: array
        variables:
          additionalProperties: true
          description: >-
            Values the nodes' extraction_variables captured, by variable name,
            as the model extracted them; {} when none.
          maxProperties: 256
          type: object
      required:
        - nodes_visited
        - variables
      type: object
    AnalysisTemplateResult:
      description: >-
        The template the analysis chose. Present only when the call's agent
        revision had analysis.templates.
      properties:
        error:
          properties:
            code:
              enum:
                - catalog_unavailable
                - catalog_empty
                - invalid_choice
                - model_failed
              type: string
            message:
              type: string
          type: object
        language:
          type: string
        missing:
          description: 'selected only, always present: declared keys left unfilled.'
          items:
            type: string
          type: array
        name:
          type: string
        reason:
          maxLength: 500
          type: string
        status:
          enum:
            - selected
            - none
            - failed
          type: string
        variables:
          additionalProperties:
            maxLength: 1000
            type: string
          description: >-
            selected only, always present: the declared keys the conversation
            established.
          type: object
      required:
        - status
      type: object
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your workspace secret key, `sk_live_` followed by 32 hex characters.
        Create one in the console under **Developers**.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.