Graine AI

Place a call

Place one outbound call now, or schedule it for later.

Place one outbound call now, or schedule it for later.

The response always carries execution_id — the id the call runs under for its entire lifetime, minted here BEFORE anything can fail. That is what makes an unconfirmed dial safe: if the telephony service stops responding mid-request the call may already be live, and a client that redials would ring the customer twice. Poll GET /v2/calls/{execution_id} instead; the id is already yours.

Immediate (no scheduled_at) — 201, status: "queued". The dial is wrapped in your organization's concurrency gate, so a burst of requests queues against your line limit rather than overrunning it. If no line frees up within a few seconds you get a 429 naming the limit, with Retry-After.

Scheduled (scheduled_at set) — 202, status: "scheduled". The call is written to durable storage and armed; it survives a deploy, and a background sweep re-fires anything a lost job would have missed. Cancel it any time before it dials with POST /v2/calls/{execution_id}/stop. It is listed in GET /v2/calls from this moment, not from the moment it rings, so a call waiting for its window is visible in the call history like any other.

Unconfirmed — 202, status: "queued", dispatch: "pending_confirmation". The request reached the telephony service but the acknowledgement did not come back in time. The call may or may not be live. Poll; do not redial.

variables fills the {tokens} in your agent's prompt and welcome message. metadata is merged over it, so a key in both takes the metadata value.

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

POST
/v2/calls
/v2/calls

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

Request Body

application/jsonRequired

agent_id
Required
Agent Id

The agent that will conduct the call. Must belong to your organization. If it carries a calling window, that window decides when this call may ring — see scheduled_at.

Minimum length: 1

to_number
Required
To Number

Recipient in E.164 format, e.g. +919812345678 (7-15 digits).

Minimum length: 1

from_numberFrom Number | null

Caller ID in E.164 format. Omit to let the telephony service pick one of the numbers registered to your organization.

variablesVariables

Prompt variables. Every {token} in the agent's prompt and welcome message is filled from here.

metadataMetadata

Additional context merged OVER 'variables' — on a key present in both, the value here wins.

scheduled_atScheduled At | null

ISO-8601 timestamp WITH a UTC offset (+05:30, -08:00, or Z). Must be at least 2 minutes and at most 30 days ahead. Omit to place the call immediately.

If the agent carries a calling window, a time outside it is NOT refused — the call is moved to a time INSIDE the next open window, and the 202 reports that time in scheduled_at with deferred_by_calling_guard: true. So this field is a request, and the response is the answer. The same applies when you omit it: an immediate call outside the window is scheduled rather than dialled.

The time is spread across the window, not stacked on its opening minute: ten calls held overnight against 09:00-21:00 land at ten different times through the day. It is derived from the execution id, so it is stable — re-reading the call returns the same time, and it never falls before the window opens or in its last five minutes.

recordRecord

Record the call audio. Applies to a scheduled call too — it is stored with the call and used at the moment it dials.

Default: true

timeout_secondsTimeout Seconds

How long to let the recipient's phone ring before giving up. Applies to a scheduled call too.

Default: 30Minimum: 5Maximum: 120

Query Parameters

organization_idOrganization Id

Optional. Must equal your key's organization.

Response Body

201

Call accepted and being placed.

execution_id
Required
Execution Id

Track the call with this id for its whole life.

status
Required
Status

Always "queued".

call_sidCall Sid | null

Provider-side leg id, for support tickets only.

agent_id
Required
Agent Id

The agent conducting the call.

to_number
Required
To Number

Recipient dialled.

from_numberFrom Number | null

Caller ID used.

created_atCreated At | null

When the call was accepted.

202

Either the call is scheduled for later (status "scheduled", with the time it will ring), or the dial was accepted and not confirmed in time (status "queued", dispatch "pending_confirmation"). Never redial on this status — the execution_id is already yours; poll it.

response
Required
Response 202 Create Call V2 Calls Post

400

1000 — malformed or contradictory input. 1002 — a required parameter is missing.

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.

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.

402

1400 — your credit balance cannot fund this call. Top up and retry.

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.

504

1502 — a service this endpoint depends on did not answer in time.

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 POST "https://api.graine.ai/v2/calls?organization_id=string" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "6c6f4cc3-f56c-479d-8422-7f76694daa29",
    "to_number": "+919812345678",
    "from_number": "+917971442184",
    "variables": {
      "callee_name": "Raju",
      "scheme": "Bullet Mega Cistern"
    },
    "metadata": {
      "crm_lead_id": "LD-88421"
    },
    "scheduled_at": "2027-03-02T09:30:00+05:30",
    "record": true,
    "timeout_seconds": 30
  }'

Call accepted and being placed.

{
  "execution_id": "dbcffa37-92a1-4ae7-9814-71ca7b8ab3d3",
  "status": "queued",
  "call_sid": "0d76fa8c-ea49-4d78-9e5b-1a15ab7b3ac2",
  "agent_id": "6c6f4cc3-f56c-479d-8422-7f76694daa29",
  "to_number": "+919812345678",
  "from_number": "+917971442184",
  "created_at": "2026-08-26T12:19:54.580Z"
}