{"openapi":"3.1.0","info":{"title":"Essere Voice API","description":"The Essere Voice API gives you programmatic access to your AI voice agents:\ncalls, transcripts, insights, appointments, contacts, phone numbers, usage,\nand outbound webhooks.\n\n## Base URL\n\n```\nhttps://voice-public-api.essere.ai/v1\n```\n\n## Authentication\n\nSend your API key on every request (from an environment variable or\nsecret store — never hard-code it):\n\n```\nAuthorization: Bearer $ESSERE_API_KEY\n```\n\nKeys are created in the Essere dashboard under **Developers**\n(Pro plan required). Staging keys start with `vk_test_`. Keys are shown once\nat creation — store them securely and never commit them.\n\nScopes: `read` (all GET endpoints) and `read_write` (also POST/PATCH/DELETE,\nincluding webhook-endpoint management).\n\n## Rate limits\n\n120 requests per minute per key, enforced as a fixed one-minute window —\nbursts straddling a window boundary can briefly exceed the nominal rate, so\nsize your client-side throttling to the limit, not to the boundary behavior.\nEvery response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and\n`X-RateLimit-Reset`; `429` responses add `Retry-After`.\n\n## Pagination\n\nList endpoints are cursor-based: pass `limit` (default 25, max 100) and\n`cursor`. Responses are a list envelope:\n\n```json\n{\"object\": \"list\", \"data\": [], \"has_more\": true, \"next_cursor\": \"...\"}\n```\n\nIterate by passing `next_cursor` back as `cursor` until `has_more` is `false`.\n\n## Idempotency\n\nPOST/PATCH endpoints honor an `Idempotency-Key` header (any unique string,\n24h window). Retried requests with the same key return the stored response\nwith `Idempotent-Replayed: true`.\n\n## Errors\n\nErrors are JSON with a stable machine-readable code:\n\n```json\n{\"error\": {\"type\": \"authentication_error\", \"code\": \"invalid_api_key\", \"message\": \"...\"}}\n```\n\n| HTTP | `type` | `code` | Meaning |\n|------|--------|--------|---------|\n| 400 | `invalid_request_error` | `invalid_request` | Malformed parameters or body (`param` names the field). |\n| 400 | `invalid_request_error` | `invalid_cursor` | The pagination cursor is not valid. |\n| 400 | `invalid_request_error` | `invalid_phone` | The phone number is not valid E.164. |\n| 401 | `authentication_error` | `invalid_api_key` | Missing, malformed, or revoked API key. |\n| 403 | `permission_error` | `plan_required` | The account is not on the Pro plan. Upgrade in the dashboard. |\n| 403 | `permission_error` | `insufficient_scope` | The key is `read`-scoped but the endpoint needs `read_write`. |\n| 403 | `permission_error` | `account_inactive` | The account is not active. Reactivate it in the dashboard. |\n| 404 | `not_found_error` | `resource_not_found` | No such resource on this account. |\n| 409 | `idempotency_error` | `idempotency_conflict` | `Idempotency-Key` reused with a different request body. |\n| 413 | `invalid_request_error` | `request_too_large` | The request body exceeds the 1 MB limit. |\n| 429 | `rate_limit_error` | `rate_limit_exceeded` | Too many requests — honor `Retry-After`. |\n| 5xx | `api_error` | `internal_error` | Something went wrong on our side. Safe to retry with backoff. |\n| 503 | `api_error` | `service_unavailable` | A dependent service is temporarily unavailable — retry. |\n\n## Webhooks\n\nSubscribe to events (`call.completed`, `call.transferred`,\n`appointment.booked`, `appointment.cancelled`, `lead.captured`,\n`usage.threshold_reached`) via the Webhook Endpoints resource. Payloads are\nsigned with `X-Essere-Signature` — see the\n[webhooks guide](https://voice-developers.essere.ai/webhooks).\n\n## More\n\nGuides, recipes, and an AI-ready `llms.txt` live at\n[voice-developers.essere.ai](https://voice-developers.essere.ai). An MCP\nserver is available at `https://voice-public-api.essere.ai/mcp` (same API keys).\n","version":"1.0.0"},"servers":[{"url":"https://voice-public-api.essere.ai"}],"paths":{"/v1/calls":{"get":{"tags":["Calls"],"summary":"List calls","description":"Returns your calls, newest first. Filter by ISO-8601 date range (`from`/`to`), `agent`, `direction`, or `status`. Summary and insight fields are included inline when available; fetch `/v1/calls/{id}/transcript` for full turns. Cursor-paginated.","operationId":"list_calls_v1_calls_get","parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only calls started at/after this ISO 8601 timestamp","title":"From"},"description":"Only calls started at/after this ISO 8601 timestamp"},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only calls started at/before this ISO 8601 timestamp","title":"To"},"description":"Only calls started at/before this ISO 8601 timestamp"},{"name":"agent","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by agent id (agt_...)","title":"Agent"},"description":"Filter by agent id (agt_...)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by call status","title":"Status"},"description":"Filter by call status"},{"name":"direction","in":"query","required":false,"schema":{"anyOf":[{"enum":["inbound","outbound"],"type":"string"},{"type":"null"}],"description":"Filter by call direction","title":"Direction"},"description":"Filter by call direction"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor from next_cursor","title":"Cursor"},"description":"Opaque cursor from next_cursor"}],"responses":{"200":{"description":"A page of calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallList"},"example":{"object":"list","data":[{"id":"call_9f8e7d6c5b4a3f2e1d0c9b8a","agent_id":"agt_1a2b3c4d5e6f7a8b9c0d1e2f","direction":"inbound","status":"completed","started_at":"2026-07-17T14:03:22Z","ended_at":"2026-07-17T14:07:45Z","duration_seconds":263,"from_number":"+35799123456","summary":"Caller asked about availability for a 2-bedroom apartment; agent booked a viewing.","sentiment":"positive","outcome":"booked","has_recording":true}],"has_more":false}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/calls/{call_id}":{"get":{"tags":["Calls"],"summary":"Retrieve a call","description":"Fetch one call by ID, including summary, sentiment, outcome, duration, and numbers.","operationId":"get_call_v1_calls__call_id__get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"The call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallResource"},"example":{"id":"call_9f8e7d6c5b4a3f2e1d0c9b8a","agent_id":"agt_1a2b3c4d5e6f7a8b9c0d1e2f","direction":"inbound","status":"completed","started_at":"2026-07-17T14:03:22Z","ended_at":"2026-07-17T14:07:45Z","duration_seconds":263,"from_number":"+35799123456","summary":"Caller asked about availability for a 2-bedroom apartment; agent booked a viewing.","sentiment":"positive","outcome":"booked","has_recording":true}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/calls/{call_id}/transcript":{"get":{"tags":["Calls"],"summary":"Retrieve a call transcript","description":"Fetch the structured transcript of a call: ordered turns with role (`agent` or `caller`) and text.","operationId":"get_transcript_v1_calls__call_id__transcript_get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"The transcript.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscriptResponse"},"example":{"call_id":"call_9f8e7d6c5b4a3f2e1d0c9b8a","turns":[{"role":"agent","text":"Hi, you've reached Horizon Estates. How can I help?"},{"role":"caller","text":"I'm calling about the two-bedroom on Makarios Avenue."}]}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/calls/{call_id}/insights":{"get":{"tags":["Calls"],"summary":"Retrieve call insights","description":"Fetch extracted insights for a call: sentiment, outcome, whether a lead was captured, and structured extracted fields.","operationId":"get_insights_v1_calls__call_id__insights_get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"The insights.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsResponse"},"example":{"call_id":"call_9f8e7d6c5b4a3f2e1d0c9b8a","sentiment":"positive","outcome":"booked","lead_captured":true,"extracted":{"budget":"250000","bedrooms":"2"}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/calls/{call_id}/recording":{"get":{"tags":["Calls"],"summary":"Stream the call recording","description":"Streams the call recording audio. The response body is the audio file itself (no URL indirection).","operationId":"get_call_recording_v1_calls__call_id__recording_get","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}}],"responses":{"200":{"description":"The recording audio stream.","content":{"application/json":{"schema":{}},"audio/mpeg":{}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage":{"get":{"tags":["Usage"],"summary":"Retrieve current-period usage","description":"Minutes used vs. allowance (plan + top-ups) and call count for the current billing period.","operationId":"get_usage_v1_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResource"}}}}}}},"/v1/agents":{"get":{"tags":["Agents"],"summary":"List agents","description":"List the account's AI voice agents with status, language, and default-agent flag. Archived agents are hidden unless `include_archived=true`.","operationId":"list_agents_v1_agents_get","parameters":[{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Archived"}}],"responses":{"200":{"description":"A list of agents.","content":{"application/json":{"schema":{},"example":{"object":"list","data":[{"id":"agt_1a2b3c4d5e6f7a8b9c0d1e2f","name":"Reception Agent","status":"active","language":"en","is_default":true,"created_at":"2026-06-01T09:12:00Z"}],"has_more":false}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/agents/{agent_id}":{"get":{"tags":["Agents"],"summary":"Retrieve an agent","description":"Fetch one agent by ID, including archived agents.","operationId":"get_agent_v1_agents__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","title":"Agent Id"}}],"responses":{"200":{"description":"The agent.","content":{"application/json":{"schema":{},"example":{"id":"agt_1a2b3c4d5e6f7a8b9c0d1e2f","name":"Reception Agent","status":"active","language":"en","is_default":true,"created_at":"2026-06-01T09:12:00Z"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/numbers":{"get":{"tags":["Numbers"],"summary":"List phone numbers","description":"List the account's phone numbers with `kind` (platform, purchased, or external), verification `status`, and assigned agent.","operationId":"list_numbers_v1_numbers_get","responses":{"200":{"description":"A list of phone numbers.","content":{"application/json":{"schema":{},"example":{"object":"list","data":[{"id":"num_3c4d5e6f7a8b9c0d1e2f3a4b","phone_number":"+35722123456","country":"CY","kind":"purchased","status":"active","agent_id":"agt_1a2b3c4d5e6f7a8b9c0d1e2f"}],"has_more":false}}}}}}},"/v1/appointments":{"get":{"tags":["Appointments"],"summary":"List appointments","description":"List appointments booked by the account's agents (booked or cancelled), timezone-aware, with attendee details. Filter by date range (`from`/`to`), `status`, or `agent_id`. Cursor-paginated.","operationId":"list_appointments_v1_appointments_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"agent_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id"}}],"responses":{"200":{"description":"A page of appointments.","content":{"application/json":{"schema":{},"example":{"object":"list","data":[{"id":"apt_2b3c4d5e6f7a8b9c0d1e2f3a","agent_id":"agt_1a2b3c4d5e6f7a8b9c0d1e2f","title":"Apartment viewing","start_time":"2026-07-20T10:00:00Z","end_time":"2026-07-20T10:30:00Z","status":"booked","attendee":{"name":"Maria Georgiou","email":"maria@example.com","phone":"+35799123456"},"location":"Makarios Avenue 12"}],"has_more":false}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contacts":{"get":{"tags":["Contacts"],"summary":"List contacts","description":"List contact records, ordered by most-recently-updated. Filter by exact `phone` (E.164), `external_id`, or `updated_since` for incremental CRM sync. Cursor-paginated.","operationId":"list_contacts_v1_contacts_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}},{"name":"phone","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},{"name":"external_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by your CRM's stable id","title":"External Id"},"description":"Filter by your CRM's stable id"},{"name":"updated_since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO 8601 — only contacts updated at/after this instant (incremental sync)","title":"Updated Since"},"description":"ISO 8601 — only contacts updated at/after this instant (incremental sync)"}],"responses":{"200":{"description":"A page of contacts.","content":{"application/json":{"schema":{},"example":{"object":"list","data":[{"id":"ctc_4d5e6f7a8b9c0d1e2f3a4b5c","phone":"+35799123456","name":"Maria Georgiou","email":"maria@example.com","notes":"Interested in 2-bedroom apartments, budget EUR 250k.","external_id":"crm-8842","fields":{"source":"website-form"},"created_at":"2026-07-01T09:12:00Z","updated_at":"2026-07-15T11:30:00Z"}],"has_more":false}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Contacts"],"summary":"Create or update a contact","description":"Create a contact, or upsert an existing one (matched by `external_id` first, then `phone`). The agent uses it as returning-caller context on the next call from that number. Requires the `read_write` scope; honors `Idempotency-Key`.","operationId":"create_contact_v1_contacts_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreate"}}}},"responses":{"201":{"description":"The created or updated contact.","content":{"application/json":{"schema":{},"example":{"id":"ctc_4d5e6f7a8b9c0d1e2f3a4b5c","phone":"+35799123456","name":"Maria Georgiou","email":"maria@example.com","notes":"Interested in 2-bedroom apartments, budget EUR 250k.","external_id":"crm-8842","fields":{"source":"website-form"},"created_at":"2026-07-01T09:12:00Z","updated_at":"2026-07-15T11:30:00Z"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contacts/{contact_id}":{"get":{"tags":["Contacts"],"summary":"Retrieve a contact","description":"Fetch one contact by ID.","operationId":"get_contact_v1_contacts__contact_id__get","parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","title":"Contact Id"}}],"responses":{"200":{"description":"The contact.","content":{"application/json":{"schema":{},"example":{"id":"ctc_4d5e6f7a8b9c0d1e2f3a4b5c","phone":"+35799123456","name":"Maria Georgiou","email":"maria@example.com","notes":"Interested in 2-bedroom apartments, budget EUR 250k.","external_id":"crm-8842","fields":{"source":"website-form"},"created_at":"2026-07-01T09:12:00Z","updated_at":"2026-07-15T11:30:00Z"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Contacts"],"summary":"Update a contact","description":"Update an existing contact by ID. Only provided fields change; a `fields` key set to null is removed. Requires the `read_write` scope; honors `Idempotency-Key`.","operationId":"update_contact_v1_contacts__contact_id__patch","parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","title":"Contact Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactUpdate"}}}},"responses":{"200":{"description":"The updated contact.","content":{"application/json":{"schema":{},"example":{"id":"ctc_4d5e6f7a8b9c0d1e2f3a4b5c","phone":"+35799123456","name":"Maria Georgiou","email":"maria@example.com","notes":"Interested in 2-bedroom apartments, budget EUR 250k.","external_id":"crm-8842","fields":{"source":"website-form"},"created_at":"2026-07-01T09:12:00Z","updated_at":"2026-07-15T11:30:00Z"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints":{"get":{"tags":["Webhook Endpoints"],"summary":"List webhook endpoints","description":"List your outbound webhook endpoints with their subscribed events and status.","operationId":"list_webhook_endpoints_v1_webhook_endpoints_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Webhook Endpoints"],"summary":"Create a webhook endpoint","description":"Register an outbound webhook endpoint (HTTPS URL). The signing `secret` (`whsec_...`) is returned once, on creation only — store it securely. An empty `events` array subscribes to all event types. Requires the `read_write` scope.","operationId":"create_webhook_endpoint_v1_webhook_endpoints_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/rotate-secret":{"post":{"tags":["Webhook Endpoints"],"summary":"Rotate a webhook signing secret","description":"Rotate the endpoint's signing secret. The new `whsec_` secret is shown once; the previous secret keeps verifying for 24 hours (deliveries carry two signatures during the overlap). Requires the `read_write` scope.","operationId":"rotate_webhook_endpoint_secret_v1_webhook_endpoints__endpoint_id__rotate_secret_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}":{"get":{"tags":["Webhook Endpoints"],"summary":"Retrieve a webhook endpoint","description":"Fetch one webhook endpoint by ID (the signing secret is never returned).","operationId":"get_webhook_endpoint_v1_webhook_endpoints__endpoint_id__get","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Webhook Endpoints"],"summary":"Update a webhook endpoint","description":"Update a webhook endpoint's URL, subscribed events, description, or status (`enabled`/`disabled`). Requires the `read_write` scope.","operationId":"update_webhook_endpoint_v1_webhook_endpoints__endpoint_id__patch","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Webhook Endpoints"],"summary":"Delete a webhook endpoint","description":"Delete a webhook endpoint. No further events are delivered to it. Requires the `read_write` scope.","operationId":"delete_webhook_endpoint_v1_webhook_endpoints__endpoint_id__delete","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/deliveries":{"get":{"tags":["Webhook Endpoints"],"summary":"List webhook deliveries","description":"List recent delivery attempts for an endpoint (metadata only — event payloads are not echoed back). Cursor-paginated.","operationId":"list_webhook_deliveries_v1_webhook_endpoints__endpoint_id__deliveries_get","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhook-endpoints/{endpoint_id}/ping":{"post":{"tags":["Webhook Endpoints"],"summary":"Send a test event","description":"Enqueue a `ping` test event to the endpoint through the normal delivery pipeline. Rate-limited per client. Requires the `read_write` scope.","operationId":"ping_webhook_endpoint_v1_webhook_endpoints__endpoint_id__ping_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","title":"Endpoint Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CallList":{"properties":{"object":{"type":"string","const":"list","title":"Object","description":"Always `list` for a paginated collection.","default":"list"},"data":{"items":{"$ref":"#/components/schemas/CallResource"},"type":"array","title":"Data","description":"The page of call resources."},"has_more":{"type":"boolean","title":"Has More","description":"Whether more results exist after this page."},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pass back as `cursor` to fetch the next page; null on the last page."}},"type":"object","required":["data","has_more","next_cursor"],"title":"CallList"},"CallResource":{"properties":{"id":{"type":"string","title":"Id","description":"Unique call ID.","examples":["call_9f8e7d6c5b4a3f2e1d0c9b8a"]},"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id","description":"ID of the agent that handled the call (agt_...)."},"direction":{"type":"string","enum":["inbound","outbound"],"title":"Direction","description":"`inbound` or `outbound`."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"Call lifecycle status, e.g. `completed`."},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At","description":"When the call started (UTC, ISO-8601)."},"ended_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ended At","description":"When the call ended; null while in progress."},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds","description":"Total call duration in seconds."},"from_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Number","description":"Caller phone number in E.164 format."},"to_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Number","description":"Receiving phone number in E.164 format; null in v1."},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"One-paragraph AI summary of the call."},"sentiment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sentiment","description":"Overall caller sentiment: `positive`, `neutral`, or `negative`."},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome","description":"Detected outcome, e.g. `booked`, `lead`, `transferred` (lowercased)."},"has_recording":{"type":"boolean","title":"Has Recording","description":"Whether recording audio is available at `/v1/calls/{id}/recording`."}},"type":"object","required":["id","agent_id","direction","status","started_at","ended_at","duration_seconds","from_number","to_number","summary","sentiment","outcome","has_recording"],"title":"CallResource"},"ContactCreate":{"properties":{"phone":{"type":"string","title":"Phone","description":"E.164, e.g. +35799123456. Upsert key (fallback)."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Contact name; used by the agent as returning-caller context."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Contact email address."},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Operator-facing notes; never spoken by the agent."},"external_id":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"External Id","description":"Your CRM's stable id. When set, upsert matches it FIRST (before phone)."},"fields":{"additionalProperties":true,"type":"object","title":"Fields","description":"Custom key/value fields surfaced to the agent as caller context."}},"type":"object","required":["phone"],"title":"ContactCreate"},"ContactUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"New contact name."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"New contact email address."},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"New operator-facing notes."},"external_id":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"External Id","description":"New CRM stable id for this contact."},"fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Fields","description":"Custom fields to shallow-merge; a key set to null is removed."}},"type":"object","title":"ContactUpdate"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InsightsResponse":{"properties":{"call_id":{"type":"string","title":"Call Id","description":"ID of the call these insights belong to."},"sentiment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sentiment","description":"Overall caller sentiment: `positive`, `neutral`, or `negative`."},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome","description":"Detected call outcome, e.g. `booked`, `lead`, `transferred`."},"lead_captured":{"type":"boolean","title":"Lead Captured","description":"Whether a lead was captured on this call."},"extracted":{"additionalProperties":true,"type":"object","title":"Extracted","description":"Structured lead/intent fields captured on the call."}},"type":"object","required":["call_id","sentiment","outcome","lead_captured","extracted"],"title":"InsightsResponse"},"TranscriptResponse":{"properties":{"call_id":{"type":"string","title":"Call Id","description":"ID of the call this transcript belongs to."},"turns":{"items":{"$ref":"#/components/schemas/TranscriptTurn"},"type":"array","title":"Turns","description":"Ordered conversation turns, earliest first."}},"type":"object","required":["call_id","turns"],"title":"TranscriptResponse"},"TranscriptTurn":{"properties":{"role":{"type":"string","enum":["agent","caller"],"title":"Role","description":"Who spoke this turn: `agent` or `caller`."},"text":{"type":"string","title":"Text","description":"The text of this turn."}},"type":"object","required":["role","text"],"title":"TranscriptTurn"},"UsageMinutes":{"properties":{"used":{"type":"number","title":"Used","description":"Plan minutes used this period"},"included":{"type":"number","title":"Included","description":"Minutes included in the plan"},"topup_used":{"type":"number","title":"Topup Used","description":"Top-up minutes used this period"},"topup_remaining":{"type":"number","title":"Topup Remaining","description":"Top-up minutes still available"},"total_used":{"type":"number","title":"Total Used","description":"used + topup_used"},"total_allowance":{"type":"number","title":"Total Allowance","description":"Everything available this period"}},"type":"object","required":["used","included","topup_used","topup_remaining","total_used","total_allowance"],"title":"UsageMinutes"},"UsageResource":{"properties":{"plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan","description":"Current plan tier"},"period_start":{"type":"string","title":"Period Start","description":"Start of the current billing period (UTC, ISO-8601)."},"period_end":{"type":"string","title":"Period End","description":"End of the current billing period (UTC, ISO-8601)."},"minutes":{"$ref":"#/components/schemas/UsageMinutes","description":"Minute usage breakdown for the current period."},"call_count":{"type":"integer","title":"Call Count","description":"Number of calls in the current billing period."}},"type":"object","required":["plan","period_start","period_end","minutes","call_count"],"title":"UsageResource"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WebhookEndpointCreate":{"properties":{"url":{"type":"string","maxLength":500,"title":"Url","description":"Public HTTPS URL to deliver events to."},"events":{"items":{"type":"string"},"type":"array","title":"Events","description":"Event types to subscribe to; an empty list subscribes to all event types."},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description","description":"Optional label for this endpoint."}},"type":"object","required":["url"],"title":"WebhookEndpointCreate"},"WebhookEndpointUpdate":{"properties":{"url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Url","description":"New public HTTPS delivery URL."},"events":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Events","description":"New list of subscribed event types."},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description","description":"New label for this endpoint."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"Set to `enabled` or `disabled` to pause or resume deliveries."}},"type":"object","title":"WebhookEndpointUpdate"}}},"tags":[{"name":"Calls","description":"Completed and in-progress calls handled by your agents, with transcripts, insights, and recording audio."},{"name":"Appointments","description":"Appointments booked (or cancelled) by your agents, timezone-aware, with agent attribution."},{"name":"Agents","description":"Your AI voice agents (read-only in v1)."},{"name":"Numbers","description":"Phone numbers connected to your agents and their verification status."},{"name":"Contacts","description":"Contact records you push to us. The agent uses them as returning-caller context on the next call from that phone number."},{"name":"Usage","description":"Plan minutes, top-ups, and call counts for the current billing period."},{"name":"Webhook Endpoints","description":"Manage outbound webhook endpoints: subscriptions, delivery log, ping test-sends. Requires read_write scope."}]}