{"openapi":"3.1.0","info":{"title":"Ody API","version":"2026-08-17","description":"The Ody REST API: contacts, conversations, SMS/MMS sending, call history,\nphone numbers (search, buy, route), 10DLC registration, outbound AI calls,\nAI agent configuration, and outbound webhooks for your workspace.\n\n**Agent Phone** — everything an AI agent provisions through this API (numbers,\n10DLC, calls) appears in the customer's account exactly as if they did it in the\napp: same billing, same gates, same timeline. A human can take over at any moment.\n\n**Authentication** — every request sends `Authorization: Bearer <key>`.\n`ody_live_…` keys are live; `ody_test_…` keys behave identically but message\nsends are **simulated** (recorded with deliveryStatus `simulated`, no SMS is sent).\n\n**Rate limits** — 600 requests/minute per key. Every response carries\n`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`; a 429 adds `Retry-After`.\n\n**Idempotency** — send an `Idempotency-Key` header on `POST /messages`; retries\nwithin 24h replay the stored response (`Idempotency-Replayed: true`).\n\n**Request ids** — every response carries `X-Request-Id`; error bodies echo it.\n\n**Webhooks** — deliveries are signed per [Standard Webhooks](https://www.standardwebhooks.com):\nheaders `webhook-id`, `webhook-timestamp`, `webhook-signature` (`v1,<base64 HMAC-SHA256>`\nover `id.timestamp.body`, key = base64-decoded secret after `whsec_`).\n\n**MCP** — the same workspace is exposed as Model Context Protocol tools at\n`POST /v1/mcp` (Streamable HTTP) with the same keys and scopes."},"servers":[{"url":"https://api.ody.co","description":"Production"},{"url":"https://ody-api-rtvqk5tg2a-uc.a.run.app","description":"Production (direct Cloud Run URL)"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Workspace API key (ody_live_… or ody_test_…) from Settings → Developer API."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}},"ContactSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"company":{"type":["string","null"]},"phone":{"type":["string","null"],"description":"First phone value, if any."},"createdAt":{"type":"string","format":"date-time"}}},"ContactDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"company":{"type":["string","null"]},"phones":{"type":"array","items":{"type":"object","required":["value"],"properties":{"value":{"type":"string"},"label":{"type":"string"}}}},"emails":{"type":"array","items":{"type":"object","required":["value"],"properties":{"value":{"type":"string"},"label":{"type":"string"}}}},"notes":{"type":"array","items":{"type":"string"}},"properties":{"type":"object","additionalProperties":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"source":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}},"ContactInput":{"type":"object","description":"At least one identity field is required on create: firstName, lastName, company, phone/phones, or email/emails.","properties":{"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"company":{"type":["string","null"]},"phone":{"type":"string","description":"Convenience scalar — merged into phones. E.164, e.g. +15125550123."},"email":{"type":"string","description":"Convenience scalar — merged into emails."},"phones":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object","required":["value"],"properties":{"value":{"type":"string"},"label":{"type":"string"}}}]},"description":"Full phone list; strings or {value,label} objects."},"emails":{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"object","required":["value"],"properties":{"value":{"type":"string"},"label":{"type":"string"}}}]}},"notes":{"type":"array","items":{"type":"string"}},"properties":{"type":"object","additionalProperties":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}}}},"ConversationSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"inboxId":{"type":"string","format":"uuid"},"numberE164":{"type":["string","null"],"description":"The Ody number the thread lives on."},"participants":{"type":"array","items":{"type":"string"}},"contactName":{"type":"string"},"status":{"type":"string","enum":["open","done"]},"assigneeUid":{"type":["string","null"]},"lastActivityAt":{"type":"string","format":"date-time"},"preview":{"type":["string","null"]},"unread":{"type":"integer"}}},"Activity":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","description":"message | call | voicemail | internal_note | system"},"direction":{"type":["string","null"],"enum":["inbound","outbound",null]},"authorUid":{"type":["string","null"]},"body":{"type":["string","null"]},"media":{"type":"array","items":{"type":"object","properties":{"url":{"type":["string","null"],"description":"Short-lived signed URL."},"contentType":{"type":"string"},"size":{"type":"integer"},"filename":{"type":"string"}}}},"deliveryStatus":{"type":["string","null"],"description":"queued | sent | delivered | failed | received | simulated (test keys)"},"call":{"type":["object","null"],"description":"Call metadata: status, duration, transcript, …"},"aiTags":{"type":"array","items":{"type":"string"}},"callTranscript":{"type":["array","null"],"items":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"}}},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"},"description":"Subscribed event types, or [\"*\"] for all."},"label":{"type":["string","null"]},"status":{"type":"string","enum":["enabled","disabled"]},"apiVersion":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"secret":{"type":"string","description":"whsec_… signing secret — returned ONLY by create and rotate. Store it; verify deliveries per Standard Webhooks."}}},"WorkspaceNumber":{"type":"object","properties":{"e164":{"type":"string"},"type":{"type":"string","description":"local | toll_free (toll-free lines bill the $10/mo toll-free add-on)"},"voiceMode":{"type":"string","description":"agent | app | voicemail | forward"},"agentId":{"type":["string","null"]},"forwardTo":{"type":["string","null"]},"assignedUserId":{"type":["string","null"]},"status":{"type":"string"}}},"MessagingStatus":{"type":"object","description":"10DLC registration status — brand + campaign pipeline (doc 36).","properties":{"step":{"type":"string","enum":["none","profile_ready","brand_pending","brand_failed","brand_otp_pending","brand_ok","campaign_pending","campaign_active","campaign_failed"],"description":"`brand_otp_pending` (sole proprietors only): the brand is accepted but TCR is waiting for the one-time PIN texted to `business.mobilePhone` — submit it via POST /v1/api/messaging/otp/verify."},"canText":{"type":"boolean","description":"True once the campaign is carrier-approved."},"messagingProfileId":{"type":["string","null"]},"brand":{"type":["object","null"],"description":"Brand status, identityStatus, failureReasons; for sole proprietors also otpSentAt + otpMobileLast4."},"campaign":{"type":["object","null"],"description":"Campaign submission/carrier status."}}},"BusinessInput":{"type":"object","required":["displayName","email","vertical","street","city","state","postalCode"],"description":"Legal business identity for the TCR brand. Non-sole-proprietors also need companyName + ein; SOLE_PROPRIETOR needs firstName/lastName + mobilePhone (the owner's mobile — TCR texts a verification PIN to it). Phones accept +E.164 or 10-digit US.","properties":{"entityType":{"type":"string","enum":["PRIVATE_PROFIT","PUBLIC_PROFIT","NON_PROFIT","GOVERNMENT","SOLE_PROPRIETOR"],"description":"Default PRIVATE_PROFIT."},"displayName":{"type":"string"},"email":{"type":"string"},"vertical":{"type":"string","description":"TCR vertical, e.g. PROFESSIONAL, RETAIL, REAL_ESTATE."},"companyName":{"type":"string"},"ein":{"type":"string","description":"9-digit EIN (dash optional)."},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string","description":"Support phone, +E.164 (10-digit US accepted)."},"mobilePhone":{"type":"string","description":"Required for SOLE_PROPRIETOR: a mobile that can receive the TCR verification text."},"street":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"postalCode":{"type":"string"},"website":{"type":"string"},"country":{"type":"string","description":"ISO2, default US."}}},"CampaignInput":{"type":"object","description":"Optional 10DLC campaign config; sensible defaults are applied.","properties":{"useCase":{"type":"string","description":"Default MIXED."},"description":{"type":"string","description":"What the campaign is for (>= 40 chars). Built from the business name and use case when omitted."},"samples":{"type":"array","items":{"type":"string"},"maxItems":5},"optinMessage":{"type":"string"},"helpMessage":{"type":"string"},"messageFlow":{"type":"string","minLength":40,"maxLength":2048,"description":"How subscribers opt in. Describe ONE method concretely. Carriers reject flows that list several methods or reference a web form that does not exist."},"optIn":{"type":"object","description":"Structured opt-in answer for a website sign-up form (preferred). Ody composes messageFlow from it using Telnyx's digital opt-in template, so reviewers see the public URL, where the form is, the full consent wording and a screenshot link. Overrides messageFlow.","required":["method","url","location","formConfirmed"],"properties":{"method":{"type":"string","enum":["web_form"]},"url":{"type":"string","description":"Public https:// address of the page holding the SMS sign-up form."},"location":{"type":"string","description":"Where on that page the form is, e.g. 'the quote form at the bottom of the home page'."},"screenshotUrl":{"type":"string","description":"Optional public link to a screenshot of the form (required by carriers for pop-ups or login-gated forms)."},"formConfirmed":{"type":"boolean","description":"Must be true: your live form shows an unchecked, optional, standalone SMS consent checkbox with the required wording."}}},"optinKeywords":{"type":"string","description":"Keyword that opts a subscriber in (e.g. YES for a double opt-in). Default START."},"embeddedLink":{"type":"boolean"},"embeddedPhone":{"type":"boolean"}}},"Agent":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"greeting":{"type":["string","null"]},"tone":{"type":["string","null"]},"voice":{"type":["string","null"]},"language":{"type":["string","null"]},"instructions":{"type":["string","null"]},"status":{"type":"string","enum":["draft","published"]},"enabled":{"type":"boolean"},"timezone":{"type":"string"},"businessHours":{"type":"object"},"inHoursAction":{"type":"string","enum":["agent","voicemail","app","forward"]},"offHoursAction":{"type":"string","enum":["agent","voicemail","app","forward"]},"jobs":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"instructions":{"type":"string"}}}}}}}},"paths":{"/v1/api/contacts":{"get":{"summary":"List or search contacts","description":"Requires scope `contacts:read`. Newest first; `q` runs full-text search.","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"Full-text search query."},{"name":"limit","in":"query","description":"Page size (1–200, default 50).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","description":"Opaque page cursor — pass the previous response's nextCursor.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of contacts","content":{"application/json":{"schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactSummary"}},"nextCursor":{"type":["string","null"]}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"post":{"summary":"Create a contact","description":"Requires scope `contacts:write`. A phone that matches an unnamed auto-created contact adopts it (threads keep their history).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/ContactDetail"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/contacts/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Get a contact","description":"Requires scope `contacts:read`.","responses":{"200":{"description":"The contact","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/ContactDetail"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"patch":{"summary":"Update a contact","description":"Requires scope `contacts:write`. Only provided fields change; phones/emails/notes/properties/tags are replaced wholesale when supplied.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactInput"}}}},"responses":{"200":{"description":"The updated contact","content":{"application/json":{"schema":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/ContactDetail"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"delete":{"summary":"Delete a contact","description":"Requires scope `contacts:write`.","responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/conversations":{"get":{"summary":"List conversations","description":"Requires scope `conversations:read`. Newest activity first.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["open","done"]}},{"name":"limit","in":"query","description":"Page size (1–100, default 50).","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","description":"Opaque page cursor — pass the previous response's nextCursor.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of conversations","content":{"application/json":{"schema":{"type":"object","properties":{"conversations":{"type":"array","items":{"$ref":"#/components/schemas/ConversationSummary"}},"nextCursor":{"type":["string","null"]}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/conversations/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Get a conversation thread","description":"Requires scope `conversations:read`. Full activity timeline (messages, calls, voicemails with transcripts + signed media URLs).","responses":{"200":{"description":"Conversation + activities (oldest → newest)","content":{"application/json":{"schema":{"type":"object","properties":{"conversation":{"$ref":"#/components/schemas/ConversationSummary"},"activities":{"type":"array","items":{"$ref":"#/components/schemas/Activity"}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"patch":{"summary":"Update a conversation (status)","description":"Requires scope `conversations:write`. Set `status` to `open` or `done`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["open","done"]}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"conversation":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messages":{"post":{"summary":"Send an SMS/MMS","description":"Requires scope `messages:send`. Provide `conversationId` OR `to` (E.164; the conversation is created from your workspace number, honoring `from` when you own it). Supports the `Idempotency-Key` header. Test keys (`ody_test_…`) record the message with deliveryStatus `simulated` and never send a real SMS.","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":200},"description":"Retries with the same key within 24h replay the first response."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["body"],"properties":{"body":{"type":"string"},"conversationId":{"type":"string","format":"uuid"},"to":{"type":"string","description":"Recipient in E.164, e.g. +15125550123."},"from":{"type":"string","description":"One of your workspace numbers (optional)."},"mediaUrls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":10,"description":"Publicly fetchable media URLs for MMS."}}}}}},"responses":{"201":{"description":"Sent (or simulated for test keys)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/Activity"},"conversationId":{"type":"string"},"simulated":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"409":{"description":"Workspace has no active number / texting not enabled (10DLC)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messages/search":{"get":{"summary":"Search messages","description":"Requires scope `conversations:read`. Case-insensitive substring search across message bodies and stored transcripts, newest first.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size (1–100, default 25).","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Matches","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"activityId":{"type":"string"},"conversationId":{"type":"string"},"type":{"type":"string"},"direction":{"type":["string","null"]},"body":{"type":["string","null"]},"participants":{"type":"array","items":{"type":"string"}},"numberE164":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/calls":{"get":{"summary":"List call & voicemail history","description":"Requires scope `conversations:read`. Newest first, flattened across conversations.","parameters":[{"name":"limit","in":"query","description":"Page size (1–200, default 50).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Call history","content":{"application/json":{"schema":{"type":"object","properties":{"calls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"conversationId":{"type":"string"},"type":{"type":"string","enum":["call","voicemail"]},"direction":{"type":"string","enum":["inbound","outbound"]},"status":{"type":["string","null"]},"durationSec":{"type":["integer","null"]},"externalE164":{"type":"string"},"contactName":{"type":["string","null"]},"forwardedTo":{"type":["string","null"]},"callerName":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"post":{"summary":"Place an outbound AI call","description":"Requires scope `calls:place`. The workspace's PUBLISHED AI agent dials `to` from one of your numbers (default: the agent-connected line), converses, and the finished call lands on the contact's timeline with AI credits billed — exactly like an inbound AI-answered call (100 credits, <15s free). Test keys (`ody_test_…`) simulate — nothing is dialed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to"],"properties":{"to":{"type":"string","description":"Destination in E.164, e.g. +15125550123."},"from":{"type":"string","description":"Optional caller ID — one of your active numbers."}}}}}},"responses":{"201":{"description":"Call queued (or simulated for test keys)","content":{"application/json":{"schema":{"type":"object","properties":{"call":{"type":"object","properties":{"id":{"type":["string","null"],"description":"Telnyx call sid."},"to":{"type":"string"},"from":{"type":"string"},"status":{"type":"string"}}},"simulated":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"409":{"description":"No plan / agent not published / no active number / intl not enabled","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/numbers":{"get":{"summary":"List workspace phone numbers","description":"Requires scope `numbers:read`.","responses":{"200":{"description":"Numbers","content":{"application/json":{"schema":{"type":"object","properties":{"numbers":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceNumber"}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"post":{"summary":"Buy a phone number","description":"Requires scope `numbers:manage`. Orders the number and bills the workspace's plan exactly like an in-app purchase: the plan includes 1 local number, further local numbers bill as the $5/mo additional-number add-on, and a toll-free (+1 8xx) number is always the $10/mo toll-free add-on. The billed type is derived from the number itself; `type` is only a hint. Toll-free numbers are calling-only (no texting yet). Same hard gates as the app: the workspace must have a plan, (where required) a verified identity, and not be billed through the App Store when the purchase would add an add-on. Supports the `Idempotency-Key` header. Test keys (`ody_test_…`) simulate — no order, no charge.","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":200},"description":"Retries with the same key within 24h replay the first response."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phoneNumber"],"properties":{"phoneNumber":{"type":"string","description":"E.164 from /numbers/available."},"type":{"type":"string","enum":["local","toll_free"],"description":"Number type hint (default 'local'); the server derives the real type from the number."}}}}}},"responses":{"201":{"description":"Purchased (or simulated for test keys)","content":{"application/json":{"schema":{"type":"object","properties":{"number":{"$ref":"#/components/schemas/WorkspaceNumber"},"simulated":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"409":{"description":"Billing-gated / identity-unverified workspace, or the number is gone","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/numbers/available":{"get":{"summary":"Search numbers available to buy","description":"Requires scope `numbers:manage`. Live carrier inventory with Ody's retail monthly price per type: local numbers are quoted at the $5/mo additional-number price (the first is included with the plan); toll-free numbers at the $10/mo toll-free add-on. `phone_number_type` in each result is Ody's classification (`local` | `toll_free`).","parameters":[{"name":"country","in":"query","schema":{"type":"string","default":"US"},"description":"ISO2 code."},{"name":"type","in":"query","schema":{"type":"string","enum":["local","toll_free"],"default":"local"},"description":"Number type: local (default) or toll_free (+1 8xx; $10/mo add-on, calling-only)."},{"name":"startsWith","in":"query","schema":{"type":"string"},"description":"Leading digits (area code) — local numbers only."},{"name":"contains","in":"query","schema":{"type":"string"},"description":"Digits anywhere."},{"name":"locality","in":"query","schema":{"type":"string"},"description":"City."},{"name":"state","in":"query","schema":{"type":"string"},"description":"State / region."},{"name":"limit","in":"query","description":"Page size (1–50, default 20).","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"Candidates","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"array","items":{"type":"object","properties":{"phone_number":{"type":"string"},"phone_number_type":{"type":"string","enum":["local","toll_free"],"description":"Ody's classification of the number."},"region_information":{"type":"array","items":{"type":"object"}},"cost_information":{"type":"object","properties":{"monthly_cost":{"type":"string"},"upfront_cost":{"type":"string"},"currency":{"type":"string"}}}}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/numbers/{e164}/connect":{"parameters":[{"name":"e164","in":"path","required":true,"schema":{"type":"string"}}],"post":{"summary":"Route a number's inbound calls to the AI agent","description":"Requires scope `agent:manage`. The agent must exist (PATCH /v1/api/agent first).","responses":{"200":{"description":"Connected","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"voiceMode":{"type":"string"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/numbers/{e164}/disconnect":{"parameters":[{"name":"e164","in":"path","required":true,"schema":{"type":"string"}}],"post":{"summary":"Route a number away from the AI agent","description":"Requires scope `agent:manage`. `mode` picks who answers instead: app (ring the team, default), voicemail, or forward (needs `forwardTo`).","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["app","voicemail","forward"],"default":"app"},"forwardTo":{"type":"string","description":"E.164 forward target (mode 'forward')."}}}}}},"responses":{"200":{"description":"Disconnected","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"voiceMode":{"type":"string"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messaging":{"get":{"summary":"10DLC registration status","description":"Requires scope `numbers:manage`. Where the workspace is in the brand → campaign pipeline and whether outbound texting is unlocked.","responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"type":"object","properties":{"messaging":{"$ref":"#/components/schemas/MessagingStatus"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messaging/registration":{"post":{"summary":"Submit 10DLC registration (brand + campaign)","description":"Requires scope `numbers:manage`. Files the workspace's brand with The Campaign Registry via Telnyx and stages the campaign; carrier review typically takes minutes-to-days. SUBMITTING IS A PURCHASE: a live filing ends a running free trial and charges the plan, plus the one-time $20 messaging setup fee per local number, to the card on file IMMEDIATELY — before the brand or campaign is accepted (never charged again for the same number on a resubmit). Because of that, a trialing workspace must send `acknowledge_trial_end: true`, otherwise 409 `failed_precondition`; if the card declines nothing is filed. The $4/mo messaging add-on starts when the registry accepts the campaign. The owner receives an emailed receipt with a masked copy of the application. Live filings also require a chargeable subscription — a workspace without a payment method on file, with a canceled subscription, or (while trialing) without a submitted identity check gets 409 `failed_precondition` (\"Add a payment method…\"). Every filing is audit-logged with actor 'api'. Test keys (`ody_test_…`) always file in mock mode — full pipeline, no TCR submission, no fee, no billing gate.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["business"],"properties":{"business":{"$ref":"#/components/schemas/BusinessInput"},"campaign":{"$ref":"#/components/schemas/CampaignInput"},"mock":{"type":"boolean","description":"Force Telnyx mock mode (no fee)."},"acknowledge_trial_end":{"type":"boolean","description":"Required (true) when the workspace is on a free trial: confirms the customer was told that filing ends the trial today and charges the plan plus the $20 per-number setup fee immediately."}}}}}},"responses":{"201":{"description":"Submitted","content":{"application/json":{"schema":{"type":"object","properties":{"messaging":{"$ref":"#/components/schemas/MessagingStatus"},"mock":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"409":{"description":"Telnyx/TCR rejected the filing (message says why)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messaging/refresh":{"post":{"summary":"Re-check and advance 10DLC registration","description":"Requires scope `numbers:manage`. Polls Telnyx for brand/campaign status and advances the pipeline (creates the campaign once the brand is OK).","responses":{"200":{"description":"Refreshed status","content":{"application/json":{"schema":{"type":"object","properties":{"messaging":{"$ref":"#/components/schemas/MessagingStatus"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messaging/otp/verify":{"post":{"summary":"Sole proprietor: submit the SMS verification PIN","description":"Requires scope `numbers:manage`. Only meaningful while `step` is `brand_otp_pending`. TCR texts a PIN to `business.mobilePhone` when a SOLE_PROPRIETOR brand is filed; a correct PIN verifies the brand and the campaign is created immediately (response step is usually `campaign_pending`). Codes expire after 24 hours.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pin"],"properties":{"pin":{"type":"string"}}}}}},"responses":{"200":{"description":"Verified — pipeline advanced","content":{"application/json":{"schema":{"type":"object","properties":{"messaging":{"$ref":"#/components/schemas/MessagingStatus"}}}}}},"400":{"description":"Wrong or expired PIN (or missing `pin`)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"409":{"description":"The registration isn't waiting for a PIN","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/messaging/otp/resend":{"post":{"summary":"Sole proprietor: text a fresh verification PIN","description":"Requires scope `numbers:manage`. Re-sends the TCR PIN to `business.mobilePhone`. Rate-limited to one send per minute (429).","responses":{"200":{"description":"Sent","content":{"application/json":{"schema":{"type":"object","properties":{"messaging":{"$ref":"#/components/schemas/MessagingStatus"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Asked again inside the one-minute cooldown window","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/agent":{"get":{"summary":"Get the AI agent config","description":"Requires scope `agent:manage`. The agent record (null until created) plus current-cycle AI credit usage.","responses":{"200":{"description":"Agent + credits","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"oneOf":[{"$ref":"#/components/schemas/Agent"},{"type":"null"}]},"credits":{"type":["object","null"],"properties":{"cycleId":{"type":"string"},"used":{"type":"integer"},"included":{"type":"integer"},"remaining":{"type":"integer"}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"patch":{"summary":"Create or update the AI agent (draft)","description":"Requires scope `agent:manage`. Only provided fields change; `jobs` is replaced wholesale. Publish with POST /v1/api/agent/publish to make changes live.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"greeting":{"type":"string"},"tone":{"type":"string"},"voice":{"type":"string"},"language":{"type":"string"},"timezone":{"type":"string","description":"IANA timezone."},"inHoursAction":{"type":"string","enum":["agent","voicemail","app","forward"]},"offHoursAction":{"type":"string","enum":["agent","voicemail","app","forward"]},"enabled":{"type":"boolean"},"jobs":{"type":"array","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"instructions":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"Saved (draft)","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/Agent"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/agent/publish":{"post":{"summary":"Publish the AI agent","description":"Requires scope `agent:manage`. Pushes the saved config live to telephony (creates/updates the voice assistant). Test keys simulate.","responses":{"200":{"description":"Published (or simulated for test keys)","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/Agent"},"simulated":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"409":{"description":"Config incomplete (message says what's missing)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/webhook-events":{"get":{"summary":"List webhook event types","description":"Requires scope `webhooks:manage`. The catalog you can subscribe endpoints to.","responses":{"200":{"description":"Event types","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/webhooks":{"get":{"summary":"List webhook endpoints","description":"Requires scope `webhooks:manage`. Secrets are never included.","responses":{"200":{"description":"Endpoints","content":{"application/json":{"schema":{"type":"object","properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"post":{"summary":"Register a webhook endpoint","description":"Requires scope `webhooks:manage`. HTTPS only; max 50 endpoints per workspace. `events` lists types or [\"*\"]. The response includes the signing secret ONCE.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"label":{"type":"string"}}}}}},"responses":{"201":{"description":"Created — includes the whsec_ secret (shown once)","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/webhooks/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Get a webhook endpoint","responses":{"200":{"description":"The endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"patch":{"summary":"Update a webhook endpoint","description":"Patch url / events / label / status (enabled|disabled).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"label":{"type":["string","null"]},"status":{"type":"string","enum":["enabled","disabled"]}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}},"delete":{"summary":"Delete a webhook endpoint","responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/webhooks/{id}/rotate":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Rotate the signing secret","description":"Returns the NEW whsec_ secret once. Old signatures stop validating immediately.","responses":{"200":{"description":"Rotated — includes the new secret","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/webhooks/{id}/test":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Send a signed test delivery","description":"Posts a `{\"type\":\"ping\"}` event to the endpoint, signed exactly like a real delivery.","responses":{"200":{"description":"Attempt result","content":{"application/json":{"schema":{"type":"object","properties":{"delivered":{"type":"boolean"},"attempt":{"type":"object","properties":{"at":{"type":"string"},"statusCode":{"type":"integer"},"error":{"type":"string"},"durationMs":{"type":"integer"}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}},"/v1/api/webhooks/{id}/deliveries":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"List recent deliveries","description":"Delivery history with per-attempt status codes/errors — the debugging view.","parameters":[{"name":"limit","in":"query","description":"Page size (1–200, default 50).","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Deliveries, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"deliveries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"webhookId":{"type":"string"},"eventId":{"type":"string"},"status":{"type":"string","enum":["pending","success","failed"]},"attempts":{"type":"array","items":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Invalid argument","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"401":{"description":"Missing/invalid/revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"403":{"description":"Key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}},"429":{"description":"Rate limit exceeded — respect Retry-After","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthenticated","permission_denied","invalid_argument","failed_precondition","not_found","resource_exhausted","internal"]},"message":{"type":"string"},"requestId":{"type":"string","description":"Echo of X-Request-Id — quote it to support."}}}}}}}}}}}}}