API Documentation
Read your Mio call history from your code, automation platform, or CRM, and receive a webhook when each call completes with transcript, summary, and cost.
Calls are started in Mio, not over the API. There is no public endpoint for placing a call today — you start one in the web app or in the Mio widget. The API is read-and-notify: your profile, your call history, and webhooks. If you need to trigger calls programmatically, email [email protected].
On this page
Authentication
All API requests require an API key. Create one in your profile settings under Integrations.
Pass your key in the X-API-Key header:
curl https://api.mio.gg/api/v1/me \
-H "X-API-Key: sk_live_your_key_here"
API keys carry your full account permissions. Keep them secret — don't commit them to version control or expose them in client-side code.
Requests are rate-limited to 60 per minute per account across all /api/v1 endpoints. Over the limit you get a 429.
Profile
Returns your account info. Useful for verifying your API key works.
Returns your user profile. No request body needed.
Response
{
"id": "a1b2c3d4-...",
"name": "Jane",
"phoneNumber": "+15551234567",
"balance": 450
}
balance is in cents (450 = $4.50). It is a leftover prepaid balance from an
earlier version of Mio and is 0 for everyone else — calls are billed per call
against a card hold, not against this balance.
Calls
Read the calls Mio has made for you. Calls themselves are started in the web app or the Mio widget.
Returns your 25 most recent completed calls, newest first. No parameters.
Example
curl https://api.mio.gg/api/v1/calls \
-H "X-API-Key: sk_live_your_key_here"
Response 200
[
{
"id": "d4e5f6a7-...",
"direction": "outbound",
"status": "completed",
"name": "IRS",
"toNumber": "+18008291040",
"fromNumber": "+15559876543",
"instructions": "Get through to a live representative...",
"summary": "Reached a representative after 41 minutes on hold...",
"transcript": [
{ "role": "agent", "text": "Hi, I'm calling on behalf of..." },
{ "role": "user", "text": "Thanks for holding, how can I help?" }
],
"cost": 180,
"duration": 2540,
"attempt": 1,
"startedAt": "2026-07-27T18:30:05.000Z",
"endedAt": "2026-07-27T19:12:25.000Z",
"createdAt": "2026-07-27T18:30:00.000Z"
}
]
cost is the metered charge in cents, duration is in seconds.
In transcript, "agent" is Mio's voice agent and "user"
is the other end of the line. The transcript covers only the part of the call Mio was on —
when Mio bridges you in, the agent drops off and the transcript ends there.
Webhooks
Webhooks notify your server when a call completes. You get the transcript, summary, cost, and duration — everything you need to process the result.
Managing webhooks
List all your webhooks.
Create a webhook. Requires HTTPS URL. A signing secret is generated and returned once.
| Parameter | Description |
|---|---|
| url required | HTTPS endpoint that will receive POST requests. |
| events optional | Array of event types. Default: ["call.completed"] |
Fetch one webhook. The signing secret is masked — it is returned in full only on create.
Update a webhook's url, events, or active status. Setting active: true also resets the failure count.
Delete a webhook. Returns 204.
Zapier REST hooks
Two extra endpoints exist for platforms that subscribe and unsubscribe automatically. Subscriptions created this way are unsigned — see webhook security below.
Subscribe. Body: url (required), events (optional). Returns { "id": "..." }.
Unsubscribe. Body: id (required). Returns 204.
Webhook payload
When a call completes, Mio sends a POST request to each active webhook. call is the same object GET /api/v1/calls returns:
{
"event": "call.completed",
"timestamp": "1753640000",
"call": {
"id": "d4e5f6a7-...",
"direction": "outbound",
"status": "completed",
"name": "Riverside Dental",
"toNumber": "+15551234567",
"fromNumber": "+15559876543",
"instructions": "Book a cleaning, any morning this week...",
"summary": "Cleaning booked for Thursday at 9:40am.",
"transcript": [
{ "role": "agent", "text": "Hi, I'm calling on behalf of..." },
{ "role": "user", "text": "Sure, what day works?" }
],
"cost": 120,
"duration": 185,
"attempt": 1,
"startedAt": "2026-07-27T18:30:05.000Z",
"endedAt": "2026-07-27T18:33:10.000Z",
"createdAt": "2026-07-27T18:30:00.000Z"
}
}
cost is in cents, duration is in seconds.
Webhook security
A webhook created with POST /api/v1/webhooks gets a signing secret (prefixed
whsec_), returned once at creation. Mio signs every delivery to that webhook so
you can verify it came from us. Zapier-style subscriptions have no secret, so deliveries to
them carry no X-Mio-Signature header.
Headers
| Header | Description |
|---|---|
| X-Mio-Signature | HMAC-SHA256 signature of the payload. Present only when the webhook has a signing secret. |
| X-Mio-Timestamp | Unix timestamp (seconds) of when the event was sent. |
| X-Mio-Event | Event type, e.g. call.completed |
| X-Mio-Delivery | Unique delivery ID (UUID). |
Verifying signatures
The signature is computed as HMAC-SHA256(secret, "{timestamp}.{body}")
where body is the raw JSON request body.
import crypto from 'crypto';
function verifyWebhook(secret, timestamp, body, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${body}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Always use constant-time comparison to prevent timing attacks. Reject requests where the timestamp is more than 5 minutes old to prevent replay attacks.
Failure handling
If your endpoint returns a non-2xx status or times out (10s), Mio retries with exponential backoff up to 10 times. After 10 consecutive failures, the webhook is automatically disabled. Re-enable it with PUT /api/v1/webhooks/:id and { "active": true }.
Errors
The API uses standard HTTP status codes. Error responses include a JSON body with an error field.
| Status | Meaning |
|---|---|
| 400 | Invalid request body or parameters. |
| 401 | Missing or invalid API key. |
| 404 | No such webhook, or it doesn't belong to your account. |
| 429 | Rate limited — more than 60 requests in a minute. |
| 500 | Server error. Try again or contact support. |
// Example error response
{
"error": "Webhook not found"
}
Ready to build?
Create your API key and wire up your first webhook in under a minute.
Get your API keyYou're charged only when Mio reaches someone — and then for what the call actually cost.