Graine API
A voice-AI calling API — build an agent, place a call, and follow that one call from the dial to the transcript with a single id.
The Graine API places real phone calls conducted by a conversational voice agent, and gives you everything the call produced afterwards — status, duration, cost, transcript and recording.
Four resources cover the whole surface:
- Agents — the configuration that decides what the agent says and how it sounds.
- Calls — one outbound call, now or scheduled, tracked end to end.
- Campaigns — a contact list dialled by one agent, with the policy that governs it: caller IDs, calling hours, retries and follow-ups. Pause, resume and cancel.
- Account — who your key belongs to, what it has spent, and key management.
Base URL
Every path in these docs is relative to that URL. The version lives in the path,
so /v2 is a stable prefix — not a header, not a query parameter.
Your first request
If that returns your organization, your key works and you are ready for the Quickstart.
Explore
Quickstart
Key to first completed call in five requests, with the real JSON at every step.
Embed on your website
Two script tags put a voice or chat agent on your site, restricted to your domains and handed context from the page.
In-app agents
The agent inside your mobile app — it sees the screen the customer is on, acts on it, and takes or makes calls like WhatsApp. React Native, Android, iOS, Flutter.
Flow agents
Build an agent as steps and paths: fixed lines said word for word, rules that branch on your data, and events from your own systems.
Outreach workflows
What happens to each contact across calls, waits and your own systems: call, try again, tell your CRM, wait for its answer, and end with an outcome you can count.
Memory
Each person remembered across phone calls, chats and in-app calls, for prompt agents and flow agents: what the agent reads, the settings, and the lines that make it use what it knows.
Your design
Choose how the agent looks in the dashboard; the website and every SDK draw it, typeface included, with nothing in your code.
Authentication
gat_ bearer keys, the eleven scopes, how organizations are resolved, and why a dashboard session is refused.
API reference
All 69 operations and the three webhook payloads, generated from the spec the API itself emits — with a request panel that calls the live API from the page.
Webhooks
One consolidated event per call: subscribing, testing an endpoint, signature verification and the retry ladder.
Agents
Create, read, update, clone and archive agents, and list the calls an agent has run.
Calls
Place, schedule, list, stop. Then read the transcript and the recording.
Campaigns
One request: upload a contact list as JSON or CSV, set the calling policy, and start dialling.
Account
Identity, concurrency capacity, wallet balance, usage aggregates and API keys.
Errors
One envelope, thirteen stable integer codes, and the HTTP status each maps to.
Rate limits
Per-organization windows, the X-RateLimit headers, and how many calls can run at once.
Enterprise
Concurrency, tenancy isolation and the operational guarantees behind the surface.
Conventions
These hold on every endpoint, so they are stated once here rather than repeated on each page.
| Concern | Rule |
|---|---|
| Authentication | Authorization: Bearer gat_... — the only accepted form. A key sent in any other header is not read. |
| Organization | Taken from the key. The optional ?organization_id= query parameter must match the key's own organization or the request is refused. |
| Errors | Always {"error": <integer>, "message": "<sentence>"}. A success response never carries error. |
| Timestamps | ISO-8601 UTC, millisecond precision, literal Z — 2026-08-26T10:15:30.123Z. |
| Phone numbers | E.164, 7 to 15 digits, for example +14155550123. |
| Request bodies | An unknown top-level key is rejected with error 1001, so a typo'd field name fails loudly instead of silently doing nothing. Two exceptions: the objects nested inside an agent's configuration accept keys they do not know without an error, and the POST /v2/transliterate body ignores them. |
| Rate limit headers | X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset are on every response after your key is authenticated, success or failure. |
Pagination
Every list endpoint takes page (1-indexed, default 1) and page_size
(default 20, maximum 100), and returns the same envelope:
Page until has_more is false rather than dividing total yourself. On
very large collections total is a capped estimate, and on GET /v2/agents
it leaves out agents that are hidden from the list.
Identifiers
| Id | Where it comes from | What it is for |
|---|---|---|
agent_id | POST /v2/agents | Naming the agent on a call, a campaign, or a clone. |
execution_id | POST /v2/calls, or a contact in a campaign | One call, for its whole life — scheduled, ringing, in progress, finished. Transcript, recording and stop all key off it. |
campaign_id | POST /v2/campaigns | Pausing, resuming, cancelling and reporting on a contact list. |
key_id | GET /v2/api-keys | Revoking a key. Never the key itself. |
execution_id is minted before the call is placed and handed back immediately,
which is what makes the API safe to integrate against: even if a dial request
times out, the id you already hold answers GET /v2/calls/{execution_id}. Poll
it — never redial.
Rate limits at a glance
Limits are per organization, not per key, so minting more keys does not buy more quota.
| Group | Endpoints | Limit |
|---|---|---|
| Placing calls | POST /v2/calls, its stop and transfer, POST /v2/campaigns | 600 / minute (500 sustained) |
| Reading calls | GET /v2/calls and the per-call reads, GET /v2/agents/{id}/executions, GET /v2/usage | 600 / minute (500 sustained) |
| Knowledge-base uploads | The two knowledge-base uploads | 20 / minute |
| Transliteration | POST /v2/transliterate | 60 / minute |
| Everything else | Every other endpoint | 1000 / minute |
Exceeding a limit returns 429 with error code 1300 and a Retry-After
header. See Rate limits for the sliding-window details.

