Skip to main content
This documents the v1 product. It is kept for integrations already running on it. If you are building something new, start with the Quickstart.
Pass callbackUrl when you initiate a call and v1 POSTs events there as the call progresses.
v2 signs differentlyv1 uses x-signature (a bare hex HMAC over the raw body) plus x-public-key. v2 uses X-Mirai-Signature: t=…,v1=… with a replay window. If you run both, use two separate routes — the schemes are not interchangeable.

Envelope

Lifecycle events

Failure and retry events

retryProtocol on the assistant decides how many attempts follow a failure. call.lifecycle-ended is what tells you the chain is over — that is the event to close your record on, not call.failed.

end-of-call

Carries the analysis plan output and credit usage.

action events

Fired when the conversation produced a business action for you to execute.
reason is set when the action exists because something was missing: missing_address, missing_first_name, invalid_cart_data.

Signature verification

Every delivery carries two headers: There is no timestamp and no replay window in v1. Recompute the HMAC over the raw bytes and compare in constant time.

Rules

  1. Use the raw body. Sign the exact bytes received, before any JSON parsing. Re-serialising changes key order and spacing, and the digest with it.
  2. Constant-time compare. hmac.compare_digest / crypto.timingSafeEqual.
  3. Keep the private key out of the browser. It signs webhooks and authenticates API calls.
  4. Return 200 fast. Enqueue the work; do not do it inline.
  5. Expect duplicates. v1 events carry no event ID — dedupe on event.type + call.id, and make handlers idempotent.

Troubleshooting