Getting started
How do I get a key? In the console, under Developers → Create key. You get a secret key, a webhook secret and a starting wallet balance immediately, and you can rotate or revoke from the same page. If you do not have console access yet, talk to us. Is there a sandbox or test key? Not yet. There is nosk_test_ and no simulated call — every call is a real
call and costs real money. Test against your own phone with a small wallet
balance. The webhook test vector lets you build and
verify your handler without placing a call at all.
Is there an SDK?
Yes, for Python:
Idempotency-Key on every call create so a retry never dials twice,
Retry-After-aware backoff, cursor iterators, and
mirai.webhooks.verify() over the raw body. Sync and async, both credential
generations. The copy-pasteable cURL, Python and Node on every page here work
just as well — the API is small on purpose.
Calls
Why didPOST /v2/calls return 202 and not 200?
Because the phone has not rung yet. 202 means queued. The outcome arrives by
webhook, or from GET /v2/calls/{id}.
How long until the phone rings?
Normally a couple of seconds from 202. If you are at your concurrency ceiling
the call sits in queued until a slot frees — it is queued, not rejected, so
being over the ceiling never returns 429.
Can I do inbound calls?
Not yet — outbound only.
Can I transfer a call to a human?
Yes — warm transfer to a human is part of every tier, see the
feature matrix. The transfer rollout is
completing now; see the roadmap for status and ask your
account contact to enable it on your workspace.
Can I change the prompt or variables mid-call?
No. variables are static per call — create the call with what you want it to
say.
Can I get the recording or transcript?
Not through the v2 API. Recordings are retained 30 days; ask your Mirai contact if you need
access. If your use case requires that we do not record, tell us up front.
What happens if the customer does not answer?
status: no_answer, a call.failed webhook, and no charge. v2 does not retry
for you — retry from your own dialler if you want to.
One caveat: when the carrier gives us no verdict at all, an unanswered call is
reported as failed with ended_reason: "no-media" instead. Both are free, and
both mean “did not connect” — so treat no_answer, busy and failed +
no-media as one bucket in retry logic. See
ended reasons.
How do I stop a call I just started?
POST /v2/calls/{id}/abort. It works while the call is
queued, while it is ringing, and while it is live — a live call is hung up
mid-conversation. Only a call that has already ended returns 409. Aborted calls
are never billed.
Which languages work?
Hindi and Indian English are what the stack is tuned for, including
Hindi-English code-switching, which is how most real calls actually sound. Write
the prompt in the language you want spoken — Devanagari for Hindi. Other
languages: ask before you build on them.
Does the agent sound like a human?
It sounds like a good phone voice. Callers usually work out it is a machine
within a turn or two, which is why telling them up front
costs you nothing and drops early hang-ups.
Billing
What does a call cost? ₹1 per minute ont1, billed in whole minutes rounded up, minimum one minute.
A 96-second call costs ₹2.00; an 8-second call costs ₹1.00. See
Billing & tiers.
Am I charged for calls that do not connect?
No. no_answer, busy, failed and aborted are free. completed,
voicemail and timeout are billed.
Am I charged for a voicemail?
Yes — media went live and audio was generated. An 18-second voicemail is one
billed minute: ₹1.00 at t1.
What happens when I run out of credit?
POST /v2/calls returns 402 insufficient_balance
and nothing is dialled. Calls already in flight finish normally.
How do I top up?
Ask your Mirai contact — self-serve top-up is not built yet, and is on the
roadmap. Credits land as a credit row in
GET /v2/wallet/transactions and take effect
immediately.
When are t3 and t5 available?
They are documented but not live. Requesting them returns
501 tier_unavailable. Current targets: t3 in
August 2026, t5 in Q4 2026 — see the roadmap and the
feature matrix for what they will include.
Webhooks
My signature never verifies. Why? Almost always because you signed a re-serialised body. Sign the raw bytes. See raw body. Second most common: the signed string is"<t>.<raw_body>" — the timestamp and the dot are part of it, not just the body.
Do you retry failed deliveries?
Yes — six attempts with exponential backoff over roughly 36 minutes, then
dead-letter. Any 2xx stops it. See retries.
Can events arrive out of order or twice?
Yes to both. Dedupe on event.id and order your state machine by
data.call.status, not by arrival time.
Can I have more than one webhook URL?
One per call, set as webhook_url at create time. Fan out on your side.
What if my endpoint is down for an hour?
The event lands in the dead-letter queue after ~36 minutes of retries. Ops can
replay it. You can also reconcile from
GET /v2/calls — that is what the list endpoint is
for.
Limits and compliance
How many concurrent calls can I run? Pilot default is 5. It is a provisioning setting, not a code change — ask for more. See Limits. Do you enforce the 9am–9pm calling window? No. Your scheduler does. We dial when you tell us to dial. See India calling rules. Do you scrub DND numbers? No. That is your list and your obligation. Do I have to tell people it is an AI? We strongly recommend it, and it belongs infirst_message. Your legal
obligations are your own to confirm.
Operations
What is your uptime target? The API and the call path are operated as a pilot service. Ask your account contact for the current SLA before you put a revenue-critical flow behind it. Where does my data go? Media (audio, ASR, TTS, the model) runs in India. The control plane — workflow orchestration and the API — runs in Europe, off the audio path, so it adds no latency to what the caller hears. Something is broken. What do you need from me? Thecall_id (or evt_id), the UTC timestamp, and what you expected. That is
enough to pull the whole workflow history.