Graine AI

Fetch per-turn timing

How long each turn of a conversation took.

How long each turn of a conversation took.

A NEW endpoint rather than fields added to GET /calls/{id}. Existing integrations parse that response, and this is large — a long call runs to hundreds of turn rows — so it is fetched only by clients that want it and nothing already published changes shape.

Each turn reports what the agent did, in the order it did it:

heard How long the caller's words took to settle into a final transcript.

thought Time to the model's first token, and to its last.

spoke Time to the first audio of the reply, and to the end of it.

round_trip_ms The three added together: from the caller finishing speaking to the first sound of the answer. It is the only latency the person on the phone experiences, and it spans all three stages, so no single one of them can report it. It is null unless every part was measured — a two-part sum presented as three is smaller than the truth, and that is the one direction a latency figure must never be wrong in. round_trip_missing then names the stages that did not report.

measured is false when the call produced no turns, and not_measured_reason says which of three cases applies: in_progress, no_turns_completed (the call connected but nobody spoke), or never_recorded (a call from before this was captured).

Rate limit: 600 requests per minute per organization (bucket executions.list). Exceeding it returns 429 with Retry-After; the X-RateLimit-* response headers report your remaining allowance on every call.

GET
/v2/calls/{execution_id}/timing
/v2/calls/dbcffa37-92a1-4ae7-9814-71ca7b8ab3d3/timing

The Authorization access token

Authorization

Authorization
Required
Bearer <token>

Your Graine API key. Create one in the dashboard under Developers, or via POST /v2/api-keys. Send it as Authorization: Bearer <key>.

In: header

Path Parameters

execution_id
Required
Execution Id

The call's id, as returned by POST /v2/calls or GET /v2/calls.

Query Parameters

organization_idOrganization Id

Optional. Must equal your key's organization.

Response Body

200

One row per turn, or measured:false with a reason when the call produced none.

execution_idExecution Id | null

The call this timing belongs to.

measured
Required
Measured

Whether any turn was recorded.

not_measured_reasonNot Measured Reason | null

Why there is nothing: 'in_progress', 'no_turns_completed' (the call connected but nobody spoke), or 'never_recorded' (a call from before timing was captured).

setupSetup | null

One-off costs before the conversation: connecting to the transcriber and synthesizer.

turnsTurns

One entry per turn, in order.

summarySummary

The call's timing at a glance.

401

1100 — missing, unknown or inactive API key. 1101 — a browser session token was presented instead of an API key.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

403

1102 — the key is valid but lacks the scope this endpoint requires, or names another organization. GET /v2/scopes reports what a key holds.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

404

1200 — no such resource in your organization. A resource belonging to another organization answers 404, never 403.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

422

1001 — the body or query failed validation; the message names the first offending field.

error
Required
integer

Stable integer code from the error table. Branch on this, not on the message.

message
Required
string

One human-readable sentence. Wording may change; the code will not.

429

1300 — the per-organization request rate or concurrent-call limit was reached. Carries Retry-After.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

503

1501 — a service this endpoint depends on is unreachable or returned a 5xx.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

curl -X GET "https://api.graine.ai/v2/calls/dbcffa37-92a1-4ae7-9814-71ca7b8ab3d3/timing?organization_id=string" \
  -H "Authorization: Bearer <token>"

One row per turn, or measured:false with a reason when the call produced none.

{
  "execution_id": "dbcffa37-92a1-4ae7-9814-71ca7b8ab3d3",
  "measured": true,
  "not_measured_reason": "no_turns_completed",
  "setup": {
    "transcriber_connect_ms": 18,
    "synthesizer_connect_ms": 101
  },
  "turns": [
    {
      "index": 2,
      "heard": {
        "settled_ms": 21,
        "text": "haan ji suna hai aage bataiye",
        "forced": false,
        "first_token_ms": 701,
        "first_audio_ms": 61,
        "complete_ms": 901
      },
      "thought": {
        "settled_ms": 21,
        "text": "haan ji suna hai aage bataiye",
        "forced": false,
        "first_token_ms": 701,
        "first_audio_ms": 61,
        "complete_ms": 901
      },
      "spoke": {
        "settled_ms": 21,
        "text": "haan ji suna hai aage bataiye",
        "forced": false,
        "first_token_ms": 701,
        "first_audio_ms": 61,
        "complete_ms": 901
      },
      "round_trip_ms": 783,
      "round_trip_partial": false,
      "round_trip_missing": [
        "spoke"
      ]
    }
  ],
  "summary": {
    "turns": 3,
    "measured_turns": 3,
    "median_round_trip_ms": 783,
    "slowest_round_trip_ms": 1204,
    "slowest_turn": 2
  }
}