diff --git a/.prettierignore b/.prettierignore index b2e3804..e0c7b7f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,4 +3,6 @@ packages/*/dist/ coverage/ contracts/openapi.messaging.json contracts/openapi.platform.json +contracts/drafts/bansafe/openapi.messaging.json +contracts/drafts/bansafe/openapi.platform.json package-lock.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b3d54e..859000f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ## Unreleased +- Added typed BanSafe Health, telemetry, collection, findings, enforcement, + incidents, claims, and Health action reads to `Client.banSafe`. + Project and session resources now cover Safe Mode, warm-up, Ban Insurance + evidence, and Health policy settings. Dashboard-only finding acknowledgement + and appeals remain outside the server-key client. + +- Aligned public requests with the `/messaging` and `/platform` namespaces. + Typed HTTP errors now preserve the canonical nested error code and message. + - Export typed terminal Calls webhooks. `call.ended` preserves a nullable caller identity for `pod_lost`; `call.telemetry` preserves cumulative traffic values. @@ -103,7 +112,7 @@ and localized through new `calls.*` messages; `pmfa-call` follows the same controller contract. - Refreshed the Messaging and Platform contracts and the coverage ledger for - the `/api/voip/*` signaling routes and the `call.ended` / `call.telemetry` + the `/messaging/voip/*` signaling routes and the `call.ended` / `call.telemetry` webhook events. ## 0.1.0-dev.0 - 2026-08-19 diff --git a/README.md b/README.md index d473451..c84a65c 100644 --- a/README.md +++ b/README.md @@ -203,9 +203,15 @@ The organization view also exposes these management resources: - `projectTokens`: list token metadata for an explicit project - `billing`: retrieve balance and currency, inspect usage meters, list transactions and tier pricing, and update low-balance reminders -- `projects`: list, create, request production enrollment, approve, and cancel +- `banSafe`: inspect Health, telemetry collection, signal definitions, findings, + restrictions, incidents, claims, and Health action history; report and retract + customer incidents +- `projects`: list, create, request production enrollment, approve, and cancel; + retrieve and update Safe Mode, warm-up, Ban Insurance evidence, and Health + policy settings - `sessions`: list, start, stop, or delete one session; stop or delete a bounded - batch; set tier override; and create a testing session + batch; set tier override; create a testing session; and retrieve or update + the session Safe Mode override - `campaigns`: list, create, retrieve, update, delete, lifecycle actions, analytics, events, and recipients - `customers`: enable Customers for a project; create, list, retrieve, update, @@ -323,14 +329,14 @@ Every client exposes `raw.request()` for deliberate API escape hatches: ```ts const response = await client.raw.request<{ data: unknown }>({ method: "GET", - path: "/v1/operations/operation_123", + path: "/platform/operations/operation_123", query: { projectId: "project_123" }, }); ``` Organization raw paths remain relative API paths. Project raw paths are relative to the bound project and receive the encoded -`/v1/projects/{projectId}` prefix automatically. Project raw requests reject +`/platform/projects/{projectId}` prefix automatically. Project raw requests reject absolute URLs, traversal, explicit project prefixes, backslashes, and `Authorization` overrides before transport. Raw requests retain typed errors, metadata, cancellation, API versions, retry rules, and idempotency. @@ -386,7 +392,7 @@ helpers. ## QuickLink lifecycle and settings `MessagingClient.quickLinks.create()`, `retrieve()`, and `cancel()` map the -authenticated hosted lifecycle at `/api/quicklinks`. They accept organization +authenticated hosted lifecycle at `/messaging/quicklinks`. They accept organization API keys or project tokens with `quicklink:manage`; browser client tokens fail before transport. Organization keys can set `projectId` on creation, while a project token remains bound by the server. @@ -395,7 +401,7 @@ These methods expose the short-lived connection URL and status record. They do not add list, recovery, or history operations that the API does not provide. `client.quickLinkSettings.retrieve()` and `update()` map only the management -`GET /v1/quicklink` and `PUT /v1/quicklink` settings contract. The same methods +`GET /platform/quicklink` and `PUT /platform/quicklink` settings contract. The same methods on `client.project(projectId)` use the immutable project ownership context. ## Browser controllers and UI diff --git a/contracts/drafts/bansafe/README.md b/contracts/drafts/bansafe/README.md new file mode 100644 index 0000000..7b1d043 --- /dev/null +++ b/contracts/drafts/bansafe/README.md @@ -0,0 +1,9 @@ +# BanSafe draft contracts + +These files are byte-identical copies of the BanSafe API pull request specs at +the commit and hashes recorded in `source.json`. These snapshots do not claim a +merged Polymorfa source revision or published SDK parity. + +The canonical files under `contracts/` and their coverage ledger stay pinned to +the last merged source revision. Replace that pin only after the API changes +land at one exact commit and the coverage ledger has been reconciled. diff --git a/contracts/drafts/bansafe/coverage.json b/contracts/drafts/bansafe/coverage.json new file mode 100644 index 0000000..d3aa787 --- /dev/null +++ b/contracts/drafts/bansafe/coverage.json @@ -0,0 +1,199 @@ +{ + "schemaVersion": 1, + "platformSha256": "a7f9d3b449aa93ebdf1e52c5c04519dd405d963a2da59db85d43748f671c95bf", + "scope": "OpenAPI operations tagged bansafe", + "covered": 25, + "excluded": 2, + "missing": 0, + "operations": [ + { + "operationId": "listBanSafeHealth", + "method": "GET", + "path": "/platform/bansafe/health", + "status": "covered", + "sdkPath": "Client.banSafe.listHealth" + }, + { + "operationId": "getBanSafeHealth", + "method": "GET", + "path": "/platform/bansafe/health/{session}", + "status": "covered", + "sdkPath": "Client.banSafe.getHealth" + }, + { + "operationId": "listBanSafeHealthHistory", + "method": "GET", + "path": "/platform/bansafe/health/{session}/history", + "status": "covered", + "sdkPath": "Client.banSafe.listHealthHistory" + }, + { + "operationId": "listBanSafeSignals", + "method": "GET", + "path": "/platform/bansafe/signals", + "status": "covered", + "sdkPath": "Client.banSafe.listSignals" + }, + { + "operationId": "getBanSafeTelemetry", + "method": "GET", + "path": "/platform/bansafe/telemetry/{session}", + "status": "covered", + "sdkPath": "Client.banSafe.getTelemetry" + }, + { + "operationId": "listBanSafeTelemetryHistory", + "method": "GET", + "path": "/platform/bansafe/telemetry/{session}/history", + "status": "covered", + "sdkPath": "Client.banSafe.listTelemetryHistory" + }, + { + "operationId": "listBanSafeCollection", + "method": "GET", + "path": "/platform/bansafe/collection", + "status": "covered", + "sdkPath": "Client.banSafe.listCollection" + }, + { + "operationId": "listBanSafeHealthActions", + "method": "GET", + "path": "/platform/bansafe/health-actions", + "status": "covered", + "sdkPath": "Client.banSafe.listHealthActions" + }, + { + "operationId": "listBanSafeFindings", + "method": "GET", + "path": "/platform/bansafe/findings", + "status": "covered", + "sdkPath": "Client.banSafe.listFindings" + }, + { + "operationId": "acknowledgeBanSafeFinding", + "method": "POST", + "path": "/platform/bansafe/findings/{findingId}/acknowledge", + "status": "excluded", + "reason": "Requires signed-in dashboard identity; server API keys and project tokens are refused." + }, + { + "operationId": "listBanSafeEnforcement", + "method": "GET", + "path": "/platform/bansafe/enforcement", + "status": "covered", + "sdkPath": "Client.banSafe.listEnforcement" + }, + { + "operationId": "appealBanSafeEnforcement", + "method": "POST", + "path": "/platform/bansafe/enforcement/{session}/appeal", + "status": "excluded", + "reason": "Requires signed-in dashboard identity; server API keys and project tokens are refused." + }, + { + "operationId": "listBanSafeIncidents", + "method": "GET", + "path": "/platform/bansafe/incidents", + "status": "covered", + "sdkPath": "Client.banSafe.listIncidents" + }, + { + "operationId": "createBanSafeIncident", + "method": "POST", + "path": "/platform/bansafe/incidents", + "status": "covered", + "sdkPath": "Client.banSafe.createIncident" + }, + { + "operationId": "retractBanSafeIncident", + "method": "POST", + "path": "/platform/bansafe/incidents/{incidentId}/retract", + "status": "covered", + "sdkPath": "Client.banSafe.retractIncident" + }, + { + "operationId": "listBanSafeClaims", + "method": "GET", + "path": "/platform/bansafe/claims", + "status": "covered", + "sdkPath": "Client.banSafe.listClaims" + }, + { + "operationId": "getBanSafeClaim", + "method": "GET", + "path": "/platform/bansafe/claims/{claimId}", + "status": "covered", + "sdkPath": "Client.banSafe.getClaim" + }, + { + "operationId": "getProjectSafeModeCeiling", + "method": "GET", + "path": "/platform/projects/{projectId}/safe-mode", + "status": "covered", + "sdkPath": "Client.projects.getSafeMode" + }, + { + "operationId": "updateProjectSafeModeCeiling", + "method": "PUT", + "path": "/platform/projects/{projectId}/safe-mode", + "status": "covered", + "sdkPath": "Client.projects.updateSafeMode" + }, + { + "operationId": "getNumberSafeMode", + "method": "GET", + "path": "/platform/sessions/{sessionId}/safe-mode", + "status": "covered", + "sdkPath": "Client.sessions.getSafeMode" + }, + { + "operationId": "updateNumberSafeMode", + "method": "PUT", + "path": "/platform/sessions/{sessionId}/safe-mode", + "status": "covered", + "sdkPath": "Client.sessions.updateSafeMode" + }, + { + "operationId": "getProjectWarmupPlanSettings", + "method": "GET", + "path": "/platform/projects/{projectId}/warmup-plan", + "status": "covered", + "sdkPath": "Client.projects.getWarmupPlan" + }, + { + "operationId": "updateProjectWarmupPlanSettings", + "method": "PUT", + "path": "/platform/projects/{projectId}/warmup-plan", + "status": "covered", + "sdkPath": "Client.projects.updateWarmupPlan" + }, + { + "operationId": "getProjectHealthPolicySettings", + "method": "GET", + "path": "/platform/projects/{projectId}/health-policy", + "status": "covered", + "sdkPath": "Client.projects.getHealthPolicy" + }, + { + "operationId": "updateProjectHealthPolicySettings", + "method": "PUT", + "path": "/platform/projects/{projectId}/health-policy", + "status": "covered", + "sdkPath": "Client.projects.updateHealthPolicy" + }, + { + "operationId": "getInsuranceEvidenceSettings", + "method": "GET", + "path": "/platform/projects/{projectId}/insurance-evidence", + "status": "covered", + "sdkPath": "Client.projects.getInsuranceEvidence" + }, + { + "operationId": "updateInsuranceEvidenceSettings", + "method": "PUT", + "path": "/platform/projects/{projectId}/insurance-evidence", + "status": "covered", + "sdkPath": "Client.projects.updateInsuranceEvidence" + } + ] +} diff --git a/contracts/drafts/bansafe/openapi.messaging.json b/contracts/drafts/bansafe/openapi.messaging.json new file mode 100644 index 0000000..c953c56 --- /dev/null +++ b/contracts/drafts/bansafe/openapi.messaging.json @@ -0,0 +1,45303 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Polymorfa WhatsApp API", + "version": "1.0.0", + "description": "Public Polymorfa REST API for sessions, messaging, media, webhooks, campaigns, templates, client tokens, QuickLinks, and bridge routing.", + "contact": { + "name": "Polymorfa API", + "url": "https://docs.polymorfa.com" + } + }, + "servers": [ + { + "url": "https://api.polymorfa.com" + } + ], + "security": [ + { + "BearerAuth": [] + } + ], + "components": { + "schemas": { + "ConversationRef": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "sender": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + } + } + } + } + }, + "PollOption": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "hash": { + "type": "string" + } + }, + "required": [ + "name", + "hash" + ] + }, + "MessagePayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "conversation": { + "$ref": "#/components/schemas/ConversationRef" + }, + "fromMe": { + "type": "boolean" + }, + "timestamp": { + "type": "number" + }, + "pushName": { + "type": "string" + }, + "isGroup": { + "type": "boolean" + }, + "type": { + "type": "string", + "enum": [ + "text", + "image", + "video", + "audio", + "document", + "location", + "contact", + "phone_number_shared", + "poll", + "sticker", + "reaction", + "revoke", + "edited", + "unknown" + ] + }, + "text": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "ptt": { + "type": "boolean" + }, + "filename": { + "type": "string" + }, + "latitude": { + "type": "number" + }, + "longitude": { + "type": "number" + }, + "displayName": { + "type": "string" + }, + "title": { + "type": "string" + }, + "reaction": { + "type": "string" + }, + "reactionTo": { + "type": "string" + }, + "revokedId": { + "type": "string" + }, + "nativeFlowResponse": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 64 + }, + "paramsJson": { + "type": "string", + "minLength": 1, + "maxLength": 262144 + }, + "version": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "name", + "paramsJson" + ] + }, + "media": { + "type": "string" + }, + "mediaUrl": { + "type": "string" + }, + "edited": { + "type": "boolean" + }, + "pollOptions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PollOption" + } + }, + "unavailable": { + "type": "boolean" + }, + "unavailableReason": { + "type": "string" + } + }, + "required": [ + "id", + "conversation", + "fromMe", + "timestamp", + "pushName", + "isGroup", + "type" + ] + }, + "CloudMessagePayload": { + "type": "object", + "properties": { + "messageId": { + "type": "string" + }, + "conversation": { + "$ref": "#/components/schemas/ConversationRef" + }, + "timestamp": { + "type": "string" + }, + "type": { + "type": "string" + }, + "senderName": { + "type": "string" + }, + "nativeFlowResponse": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 64 + }, + "paramsJson": { + "type": "string", + "minLength": 1, + "maxLength": 262144 + }, + "version": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "name", + "paramsJson" + ] + }, + "interactive": { + "type": "object", + "additionalProperties": {} + } + }, + "required": [ + "messageId", + "conversation", + "timestamp", + "type" + ] + }, + "MessageReceivedPayload": { + "oneOf": [ + { + "$ref": "#/components/schemas/MessagePayload" + }, + { + "$ref": "#/components/schemas/CloudMessagePayload" + } + ] + }, + "MessageReceivedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.received" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessageReceivedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "MessageSentPayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "conversation": { + "$ref": "#/components/schemas/ConversationRef" + }, + "type": { + "type": "string" + }, + "timestamp": { + "type": "number" + } + }, + "required": [ + "id", + "conversation", + "type", + "timestamp" + ] + }, + "MessageSentEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.sent" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessageSentPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "IdentityRef": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "MessageAckPayload": { + "type": "object", + "properties": { + "messageIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "sender": { + "$ref": "#/components/schemas/IdentityRef" + }, + "type": { + "type": "string", + "description": "Ack type: error, delivered, read, played" + }, + "timestamp": { + "type": "number" + } + }, + "required": [ + "messageIds", + "from", + "sender", + "type", + "timestamp" + ] + }, + "MessageAckEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.ack" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessageAckPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "MessageRevokedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.revoked" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessagePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "MessageReactionEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.reaction" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessagePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "MessageEditedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.edited" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessagePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "MessageUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessagePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "MessageDeletePayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "sender": { + "$ref": "#/components/schemas/IdentityRef" + }, + "messageId": { + "type": "string" + }, + "fromMe": { + "type": "boolean" + } + }, + "required": [ + "from", + "sender", + "messageId", + "fromMe" + ] + }, + "MessageDeleteEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.delete" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessageDeletePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "PollVotePayload": { + "type": "object", + "properties": { + "pollMessageId": { + "type": "string" + }, + "voter": { + "$ref": "#/components/schemas/IdentityRef" + }, + "selectedHashes": { + "type": "array", + "items": { + "type": "string" + } + }, + "timestamp": { + "type": "number" + } + }, + "required": [ + "pollMessageId", + "voter", + "selectedHashes", + "timestamp" + ] + }, + "MessageVoteEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.vote" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/PollVotePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "SessionStatusPayload": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Session status: CONNECTING, CONNECTED, DISCONNECTED", + "example": "DISCONNECTED" + }, + "statusReason": { + "type": "string", + "description": "Reason for the status: SCAN_QR, AUTO_RECONNECT, FAILED, MANUAL_STOP, QR_TIMEOUT, LOGGED_OUT, TEMPORARY_BAN, STREAM_ERROR", + "example": "TEMPORARY_BAN" + }, + "banCode": { + "type": "integer", + "minimum": 0, + "description": "WhatsApp temporary-ban code (present only when statusReason is TEMPORARY_BAN).", + "example": 101 + }, + "banReason": { + "type": "string", + "description": "Human-readable label for the ban code (present only when statusReason is TEMPORARY_BAN).", + "example": "Suspected spam activity" + }, + "banExpiresAt": { + "type": "integer", + "description": "Unix timestamp in seconds when the temporary ban lifts, when WhatsApp provides a duration.", + "format": "int64", + "example": 1789000000 + }, + "detail": { + "type": "string", + "description": "Extra context for FAILED and STREAM_ERROR statuses (for example the connect-failure reason)." + } + }, + "required": [ + "status" + ] + }, + "SessionStatusEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "session.status" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/SessionStatusPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "SessionConnectedPayload": { + "type": "object", + "properties": { + "phoneNumber": { + "type": "string" + }, + "id": { + "type": "string" + }, + "pushName": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "businessName": { + "type": "string" + } + }, + "required": [ + "phoneNumber", + "pushName", + "platform" + ] + }, + "SessionConnectedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "session.connected" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/SessionConnectedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "SessionLoggedOutPayload": { + "type": "object", + "properties": { + "reason": { + "type": "string" + } + }, + "required": [ + "reason" + ] + }, + "SessionLoggedOutEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "session.logged_out" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/SessionLoggedOutPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "SessionPhoneOfflinePayload": { + "type": "object", + "properties": { + "daysSinceLastSeen": { + "type": "number", + "description": "Whole days since the phone was last seen online.", + "example": 11 + }, + "daysRemaining": { + "type": "number", + "description": "Days remaining before WhatsApp disconnects the session (clamped to 0). WhatsApp typically severs the companion link after ~14 days of phone inactivity.", + "example": 3 + }, + "lastSeen": { + "type": "string", + "description": "ISO 8601 timestamp of the last time the phone was seen online.", + "example": "2026-04-05T14:30:00Z" + }, + "action": { + "type": "string", + "description": "Human-readable action string to surface to the end user (e.g. ask them to open WhatsApp on their phone).", + "example": "Open WhatsApp on your phone to keep the session alive" + } + }, + "required": [ + "daysSinceLastSeen", + "daysRemaining", + "lastSeen", + "action" + ] + }, + "SessionPhoneOfflineEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "session.phone_offline" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/SessionPhoneOfflinePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "GroupUpdatePayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "newSubject": { + "type": "string" + }, + "newDescription": { + "type": "string" + }, + "action": { + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "GroupUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "group.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/GroupUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "GroupParticipantPayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "joined": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityRef" + } + }, + "left": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityRef" + } + }, + "promoted": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityRef" + } + }, + "demoted": { + "type": "array", + "items": { + "$ref": "#/components/schemas/IdentityRef" + } + } + }, + "required": [ + "id" + ] + }, + "GroupParticipantEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "group.participant" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/GroupParticipantPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "PresenceUpdatePayload": { + "type": "object", + "properties": { + "observedAt": { + "type": "integer" + }, + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "sender": { + "$ref": "#/components/schemas/IdentityRef" + }, + "state": { + "type": "string" + }, + "media": { + "type": "string" + }, + "unavailable": { + "type": "boolean" + }, + "lastSeen": { + "type": "number" + } + }, + "required": [ + "observedAt" + ] + }, + "PresenceUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "presence.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/PresenceUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "ContactUpdatePayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "fullName": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "pushName": { + "type": "string" + }, + "oldPushName": { + "type": "string" + }, + "businessName": { + "type": "string" + }, + "oldBusinessName": { + "type": "string" + }, + "pictureId": { + "type": "string" + }, + "pictureRemoved": { + "type": "boolean" + } + }, + "required": [ + "id" + ] + }, + "ContactUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "contact.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/ContactUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "ChatArchivePayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "archive": { + "type": "boolean" + }, + "pinned": { + "type": "boolean" + } + }, + "required": [ + "from" + ] + }, + "ChatArchiveEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "chat.archive" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/ChatArchivePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "ChatMutePayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "muted": { + "type": "boolean" + }, + "muteEndTimestamp": { + "type": "number" + } + }, + "required": [ + "from", + "muted" + ] + }, + "ChatMuteEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "chat.mute" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/ChatMutePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "ChatReadPayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "read": { + "type": "boolean" + } + }, + "required": [ + "from", + "read" + ] + }, + "ChatReadEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "chat.read" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/ChatReadPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "ChatClearPayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + } + }, + "required": [ + "from" + ] + }, + "ChatClearEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "chat.clear" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/ChatClearPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "ChatDeletePayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + } + }, + "required": [ + "from" + ] + }, + "ChatDeleteEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "chat.delete" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/ChatDeletePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallReceivedPayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "callId": { + "type": "string" + }, + "hasVideo": { + "type": "boolean", + "description": "Whether the offered call advertised video.", + "example": false + } + }, + "required": [ + "from", + "callId", + "hasVideo" + ] + }, + "CallReceivedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.received" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallReceivedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallMissedPayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "callId": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "from", + "callId", + "reason" + ] + }, + "CallMissedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.missed" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallMissedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallAcceptedPayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "callId": { + "type": "string" + } + }, + "required": [ + "from", + "callId" + ] + }, + "CallAcceptedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.accepted" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallAcceptedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallRejectedPayload": { + "type": "object", + "properties": { + "from": { + "$ref": "#/components/schemas/IdentityRef" + }, + "callId": { + "type": "string" + } + }, + "required": [ + "from", + "callId" + ] + }, + "CallRejectedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.rejected" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallRejectedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallEndedPayload": { + "type": "object", + "properties": { + "from": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id" + ] + }, + "callId": { + "type": "string" + }, + "durationSeconds": { + "type": "integer", + "description": "Total connected duration in seconds (0 if never answered).", + "example": 42 + }, + "reason": { + "type": "string", + "description": "Termination reason: user_hangup | timeout | lost_connection | rejected | capacity | pod_lost.", + "example": "user_hangup" + }, + "direction": { + "type": "string", + "enum": [ + "inbound", + "outbound" + ], + "description": "Call direction.", + "example": "inbound" + }, + "hadVideo": { + "type": "boolean", + "description": "Whether the call carried video.", + "example": false + } + }, + "required": [ + "from", + "callId", + "durationSeconds", + "reason", + "direction", + "hadVideo" + ] + }, + "CallEndedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.ended" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallEndedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallTelemetryPayload": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "setupMs": { + "type": "integer", + "description": "Time from offer to media_ready, in milliseconds.", + "example": 850 + }, + "ringMs": { + "type": "integer", + "description": "Time spent ringing before accept, in milliseconds.", + "example": 3200 + }, + "durationSeconds": { + "type": "integer", + "description": "Total connected duration in seconds.", + "example": 42 + }, + "terminateReason": { + "type": "string", + "description": "Termination reason: user_hangup | timeout | lost_connection | rejected | capacity.", + "example": "user_hangup" + }, + "codec": { + "type": "string", + "description": "Negotiated audio codec's bare subtype; empty when no codec stats.", + "example": "opus" + }, + "jitterMs": { + "type": "number", + "description": "Inbound RTP jitter for the audio stream, in milliseconds.", + "example": 12.5 + }, + "packetsLost": { + "type": "integer", + "description": "Cumulative inbound RTP packets lost for the audio stream.", + "example": 3 + }, + "rttMs": { + "type": "number", + "description": "Estimated round-trip time from the remote-inbound report, in milliseconds.", + "example": 48.2 + }, + "recvKbps": { + "type": "number", + "description": "Total inbound volume across all RTP streams, in kilobits (cumulative).", + "example": 2048 + }, + "sendKbps": { + "type": "number", + "description": "Total outbound volume across all RTP streams, in kilobits (cumulative).", + "example": 2011 + } + }, + "required": [ + "callId", + "setupMs", + "ringMs", + "durationSeconds", + "terminateReason", + "codec", + "jitterMs", + "packetsLost", + "rttMs", + "recvKbps", + "sendKbps" + ] + }, + "CallTelemetryEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.telemetry" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallTelemetryPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallParticipant": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "audioMuted": { + "type": "boolean", + "enum": [ + false + ], + "description": "Reserved; false until WhatsApp exposes authoritative participant mute state." + }, + "video": { + "type": "boolean", + "enum": [ + false + ], + "description": "Reserved; false until WhatsApp exposes authoritative participant video state." + }, + "state": { + "type": "string", + "enum": [ + "invited", + "ringing", + "connected", + "left" + ] + } + }, + "required": [ + "id", + "handle", + "audioMuted", + "video", + "state" + ] + }, + "CallParticipantPayload": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "participant": { + "$ref": "#/components/schemas/CallParticipant" + } + }, + "required": [ + "callId", + "participant" + ] + }, + "CallParticipantJoinedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.participant_joined" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallParticipantPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallParticipantStateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.participant_state" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallParticipantPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CallParticipantLeftPayload": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "participantId": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "callId", + "participantId" + ] + }, + "CallParticipantLeftEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "call.participant_left" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CallParticipantLeftPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "NewsletterUpdatePayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "action": { + "type": "string" + }, + "muted": { + "type": "boolean" + } + }, + "required": [ + "id", + "action" + ] + }, + "NewsletterUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "newsletter.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/NewsletterUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "BlocklistChange": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "action": { + "type": "string" + } + }, + "required": [ + "id", + "action" + ] + }, + "BlocklistUpdatePayload": { + "type": "object", + "properties": { + "action": { + "type": "string" + }, + "changes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BlocklistChange" + } + } + }, + "required": [ + "action", + "changes" + ] + }, + "BlocklistUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "blocklist.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BlocklistUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "LabelsUpdatePayload": { + "type": "object", + "properties": { + "action": { + "type": "string", + "description": "Action: label_edit, label_association_chat, star", + "example": "label_edit" + }, + "labelId": { + "type": "string", + "description": "Label ID affected by the action" + }, + "from": { + "allOf": [ + { + "$ref": "#/components/schemas/IdentityRef" + }, + { + "description": "Chat the label action applies to" + } + ] + }, + "label": { + "type": "string", + "description": "Legacy field: the label's display name for label_edit, and the label ID for association actions. Prefer labelId and name." + }, + "name": { + "type": "string", + "description": "Label display name (present for label_edit)" + }, + "color": { + "type": "integer", + "description": "Label color index (present for label_edit)", + "format": "int32" + }, + "orderIndex": { + "type": "integer", + "description": "Label ordering index when supplied by app state", + "format": "int32" + }, + "deleted": { + "type": "boolean", + "description": "Whether the label definition was deleted" + }, + "labeled": { + "type": "boolean", + "description": "Whether the chat or message association is active" + }, + "observedAt": { + "type": "integer", + "description": "Unix timestamp in seconds when the app-state mutation was observed", + "format": "int64" + }, + "messageId": { + "type": "string", + "description": "Message ID (present for star actions)" + }, + "starred": { + "type": "boolean", + "description": "Whether the message is starred (present for star actions)" + } + }, + "required": [ + "action" + ] + }, + "LabelsUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "labels.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/LabelsUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "BusinessQuickReplyUpdatePayload": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "shortcut": { + "type": "string" + }, + "message": { + "type": "string" + }, + "keywords": { + "type": "array", + "items": { + "type": "string" + } + }, + "count": { + "type": "integer", + "minimum": 0 + }, + "deleted": { + "type": "boolean" + }, + "associatedLabelIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "observedAt": { + "type": "integer" + }, + "fromFullSync": { + "type": "boolean" + } + }, + "required": [ + "id", + "shortcut", + "message", + "keywords", + "count", + "deleted", + "associatedLabelIds", + "observedAt", + "fromFullSync" + ] + }, + "BusinessQuickReplyUpdateEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "business.quick_reply.update" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BusinessQuickReplyUpdatePayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "HistorySyncPayload": { + "type": "object", + "properties": { + "messageId": { + "type": "string" + }, + "originalMessageId": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "deliver" + ] + }, + "syncType": { + "type": "string" + }, + "chunkOrder": { + "type": "integer", + "minimum": 0 + }, + "progress": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "fileLength": { + "type": "integer", + "minimum": 0 + }, + "conversationCount": { + "type": "integer", + "minimum": 0 + }, + "messageCount": { + "type": "integer", + "minimum": 0 + }, + "pushNameCount": { + "type": "integer", + "minimum": 0 + }, + "statusMessageCount": { + "type": "integer", + "minimum": 0 + }, + "data": { + "type": "string", + "description": "Base64-encoded gzip-compressed HistorySync protobuf" + } + }, + "required": [ + "messageId", + "mode", + "syncType", + "fileLength", + "conversationCount", + "messageCount", + "pushNameCount", + "statusMessageCount", + "data" + ] + }, + "HistorySyncEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "history.sync" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/HistorySyncPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CommandResultPayload": { + "type": "object", + "properties": { + "requestId": { + "type": "string" + }, + "command": { + "type": "string" + }, + "success": { + "type": "boolean" + }, + "data": { + "type": "object", + "additionalProperties": {} + }, + "error": { + "type": "string" + } + }, + "required": [ + "requestId", + "command", + "success" + ] + }, + "CommandResultEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "command.result" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CommandResultPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CustomerEnabledPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "migratedNumberCount": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "migratedNumberCount" + ], + "additionalProperties": false + }, + "CustomerEnabledEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.enabled" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerEnabledPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerCreatedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind" + ], + "additionalProperties": false + }, + "CustomerCreatedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.created" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerCreatedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerUpdatedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "fields": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "name", + "phone", + "externalCustomerId" + ] + }, + "minItems": 1, + "maxItems": 3 + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "fields" + ], + "additionalProperties": false + }, + "CustomerUpdatedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.updated" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerUpdatedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerArchivingPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "blockingNumberCount": { + "type": "integer", + "minimum": 0 + }, + "revokedPairingLinkCount": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "blockingNumberCount", + "revokedPairingLinkCount" + ], + "additionalProperties": false + }, + "CustomerArchivingEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.archiving" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerArchivingPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerArchivedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind" + ], + "additionalProperties": false + }, + "CustomerArchivedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.archived" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerArchivedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerRestoredPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind" + ], + "additionalProperties": false + }, + "CustomerRestoredEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.restored" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerRestoredPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerPairingLinkCreatedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "pairingLinkId" + ], + "additionalProperties": false + }, + "CustomerPairingLinkCreatedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.pairing_link.created" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerPairingLinkCreatedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerPairingLinkOpenedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "pairingLinkId" + ], + "additionalProperties": false + }, + "CustomerPairingLinkOpenedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.pairing_link.opened" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerPairingLinkOpenedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerPairingLinkConnectedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + }, + "sessionId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "pairingLinkId", + "sessionId" + ], + "additionalProperties": false + }, + "CustomerPairingLinkConnectedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.pairing_link.connected" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerPairingLinkConnectedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerPairingLinkFailedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + }, + "errorCode": { + "type": "string", + "pattern": "^[a-z0-9_]{1,64}$" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "pairingLinkId", + "errorCode" + ], + "additionalProperties": false + }, + "CustomerPairingLinkFailedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.pairing_link.failed" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerPairingLinkFailedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerPairingLinkExpiredPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "pairingLinkId" + ], + "additionalProperties": false + }, + "CustomerPairingLinkExpiredEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.pairing_link.expired" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerPairingLinkExpiredPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerPairingLinkRevokedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + }, + "reason": { + "type": "string", + "enum": [ + "customer_archived", + "phone_mismatch_limit", + "exchange_failure_limit", + "terminal_failure" + ] + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "pairingLinkId" + ], + "additionalProperties": false + }, + "CustomerPairingLinkRevokedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.pairing_link.revoked" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerPairingLinkRevokedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerNumberAttachedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "pairingLinkId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "sessionId" + ], + "additionalProperties": false + }, + "CustomerNumberAttachedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.number.attached" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerNumberAttachedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerNumberTransferredPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "sourceCustomerId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "sessionId", + "sourceCustomerId" + ], + "additionalProperties": false + }, + "CustomerNumberTransferredEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.number.transferred" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerNumberTransferredPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "CustomerNumberDisconnectedPayload": { + "type": "object", + "properties": { + "eventId": { + "type": "string", + "format": "uuid" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "type": "string", + "format": "uuid" + }, + "actorKind": { + "type": "string", + "enum": [ + "better_auth", + "org_key", + "project_token", + "cli_grant", + "system" + ] + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "reason": { + "type": "string", + "pattern": "^[a-z0-9_]{1,64}$" + } + }, + "required": [ + "eventId", + "occurredAt", + "organizationId", + "projectId", + "customerId", + "actorKind", + "sessionId", + "reason" + ], + "additionalProperties": false + }, + "CustomerNumberDisconnectedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "customer.number.disconnected" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CustomerNumberDisconnectedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "BanSafeEnforcementPayload": { + "type": "object", + "properties": { + "phoneNumber": { + "type": "string", + "pattern": "^\\+[1-9]\\d{1,14}$", + "description": "The customer's own number in E.164 format.", + "example": "+15551234567" + }, + "kind": { + "type": "string", + "enum": [ + "cap_warning", + "cap_reached", + "timelock", + "temporary_ban", + "permanent_ban", + "connect_blocked", + "customer_report" + ], + "description": "Enforcement outcome, or customer_report for a customer-reported ban." + }, + "source": { + "type": "string", + "enum": [ + "runtime", + "customer" + ], + "description": "Whether Polymorfa observed the enforcement or the customer reported it." + }, + "code": { + "type": "integer", + "minimum": 0, + "description": "WhatsApp status code (for example 402, 403, 406, 475) when observed.", + "example": 402 + }, + "subCode": { + "type": "integer", + "minimum": 0, + "description": "WhatsApp sub-code (101-106 for temporary bans) when provided.", + "example": 101 + }, + "reason": { + "type": "string", + "maxLength": 200, + "description": "Sanitised reason from the WhatsApp code table.", + "example": "Suspected spam activity" + }, + "enforcementType": { + "type": "string", + "maxLength": 64, + "description": "WhatsApp enforcement type (for example BIZ_QUALITY) when provided." + }, + "startedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the enforcement started.", + "example": "2026-09-06T14:03:12.000Z" + }, + "endsAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the enforcement lifts, when WhatsApp provides a duration.", + "example": "2026-09-07T14:03:12.000Z" + } + }, + "required": [ + "phoneNumber", + "kind", + "source", + "startedAt" + ], + "additionalProperties": false + }, + "BanSafeEnforcementEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "bansafe.enforcement" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BanSafeEnforcementPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "BanSafeRequiredFinding": { + "type": "object", + "properties": { + "findingKey": { + "type": "string", + "pattern": "^[a-z0-9_]{1,64}$", + "description": "Stable finding identifier.", + "example": "typing_absent" + }, + "title": { + "type": "string", + "minLength": 1, + "maxLength": 160, + "description": "Customer-facing finding title.", + "example": "Messages sent without showing that you are typing" + }, + "severity": { + "type": "string", + "enum": [ + "info", + "warning", + "critical" + ] + } + }, + "required": [ + "findingKey", + "title", + "severity" + ], + "additionalProperties": false + }, + "BanSafeActionPayload": { + "type": "object", + "properties": { + "phoneNumber": { + "type": "string", + "pattern": "^\\+[1-9]\\d{1,14}$", + "description": "The customer's own number in E.164 format.", + "example": "+15551234567" + }, + "action": { + "type": "string", + "enum": [ + "applied", + "changed", + "lifted", + "daily_allowance_reached" + ], + "description": "Whether the restriction was newly applied, moved, or removed. `daily_allowance_reached` reports that the number spent its warm-up allowance for the day; nothing on the ladder moved and sending resumes at the next reset." + }, + "scope": { + "type": "string", + "enum": [ + "number", + "organization" + ], + "description": "Whether this covers one number or every number in the workspace." + }, + "rung": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ], + "description": "Restriction now in force." + }, + "previousRung": { + "type": "string", + "nullable": true, + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend", + null + ], + "description": "Restriction previously in force, or null when none was." + }, + "reason": { + "type": "string", + "enum": [ + "health", + "finding", + "org_pattern", + "repeat", + "restriction", + "operator", + "health_model_cutover", + "warmup" + ], + "description": "Why the restriction changed." + }, + "health": { + "type": "integer", + "nullable": true, + "minimum": 0, + "maximum": 100, + "description": "Measured health from 0 (worst) to 100 (best), or null when not measured.", + "example": 62 + }, + "healthBand": { + "type": "string", + "enum": [ + "good", + "fair", + "poor", + "failing", + "unknown" + ], + "description": "Health band matching health." + }, + "requires": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeRequiredFinding" + }, + "maxItems": 25, + "description": "Findings that must resolve before this restriction lifts." + }, + "throughputPerMinute": { + "type": "integer", + "nullable": true, + "minimum": 0, + "maximum": 10000, + "description": "Messages per minute allowed while paced, or null when not paced.", + "example": 6 + }, + "eligibleLiftAt": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "Earliest instant the restriction can step down, ISO 8601.", + "example": "2026-09-08T14:00:00.000Z" + }, + "liftRequires": { + "type": "string", + "minLength": 1, + "maxLength": 240, + "description": "One sentence describing what lifts the restriction.", + "example": "Resolve the two open checks and keep them clean for six evaluations." + }, + "appealUrl": { + "type": "string", + "maxLength": 500, + "format": "uri", + "description": "Where to appeal this action.", + "example": "https://app.polymorfa.com/safety/appeal" + }, + "startedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when this restriction took effect.", + "example": "2026-09-06T14:00:00.000Z" + }, + "docs": { + "type": "string", + "maxLength": 500, + "format": "uri", + "description": "Documentation for this restriction.", + "example": "https://docs.polymorfa.com/safety/restrictions" + } + }, + "required": [ + "phoneNumber", + "action", + "scope", + "rung", + "previousRung", + "reason", + "health", + "healthBand", + "requires", + "throughputPerMinute", + "eligibleLiftAt", + "liftRequires", + "appealUrl", + "startedAt", + "docs" + ], + "additionalProperties": false + }, + "BanSafeActionEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "bansafe.action" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BanSafeActionPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "BanSafeHealthThresholdPayload": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "format": "uuid", + "description": "Session whose present Health crossed the project threshold." + }, + "projectId": { + "type": "string", + "format": "uuid", + "description": "Project whose Health rule produced this action." + }, + "health": { + "type": "number", + "minimum": 0, + "maximum": 100, + "description": "Present Health; higher is healthier." + }, + "threshold": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "Configured project threshold crossed by this evaluation." + }, + "healthSource": { + "type": "string", + "enum": [ + "rules_v1", + "ml_model" + ], + "description": "Estimator family used by the evaluation." + }, + "estimatorVersion": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "description": "Estimator version used by the evaluation." + }, + "modelVersion": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 128, + "description": "Learned-model version, or null for a rules-based estimate." + }, + "evaluatedAt": { + "type": "string", + "format": "date-time", + "description": "Evaluation time in ISO 8601 format." + }, + "policyVersion": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991, + "description": "Project Health rule version evaluated." + }, + "episodeId": { + "type": "string", + "format": "uuid", + "description": "Stable below-threshold episode identifier." + }, + "actionId": { + "type": "string", + "format": "uuid", + "description": "Stable event identity used for retries." + } + }, + "required": [ + "sessionId", + "projectId", + "health", + "threshold", + "healthSource", + "estimatorVersion", + "modelVersion", + "evaluatedAt", + "policyVersion", + "episodeId", + "actionId" + ], + "additionalProperties": false + }, + "BanSafeHealthThresholdEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "bansafe.health_threshold" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BanSafeHealthThresholdPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "BanSafeIncidentPayload": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Incident id. Stable, quotable, and the subject of a Ban Insurance claim.", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "phoneNumber": { + "type": "string", + "pattern": "^\\+[1-9]\\d{1,14}$", + "description": "The customer's own number in E.164 format.", + "example": "+15551234567" + }, + "kind": { + "type": "string", + "enum": [ + "cap_warning", + "cap_reached", + "timelock", + "temporary_ban", + "permanent_ban", + "connect_blocked", + "customer_report" + ], + "description": "What WhatsApp did, or customer_report when you reported it." + }, + "source": { + "type": "string", + "enum": [ + "runtime", + "customer" + ], + "description": "Whether Polymorfa observed it or you reported it." + }, + "startedAt": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the restriction started.", + "example": "2026-09-06T14:03:12.000Z" + }, + "endsAt": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "ISO 8601 timestamp when the restriction ends, or null when it has no end. A ban you report ends 24 hours after the time you give unless you report it again or Polymorfa observes the restriction itself.", + "example": "2026-09-07T14:03:12.000Z" + }, + "belief": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "How confident Polymorfa is that this restriction was real, from 0 to 1. A restriction WhatsApp announced is 1. A ban you report starts at 0.9 and moves once the number's own sending shows whether it was restricted.", + "example": 1 + }, + "resolution": { + "type": "string", + "enum": [ + "open", + "corroborated", + "contradicted", + "phone_switch", + "final" + ], + "description": "How the incident settled. open: still being decided. corroborated: a report and an observed restriction agree. contradicted: the number kept sending, so there was no restriction. phone_switch: the number moved to another phone. final: settled with the confidence shown." + }, + "claimId": { + "type": "string", + "nullable": true, + "description": "The Ban Insurance claim this incident belongs to, or null when there is none.", + "example": null + }, + "closedAt": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "ISO 8601 timestamp when you closed or retracted the report, or null.", + "example": null + } + }, + "required": [ + "id", + "phoneNumber", + "kind", + "source", + "startedAt", + "endsAt", + "belief", + "resolution", + "claimId", + "closedAt" + ], + "additionalProperties": false + }, + "BanSafeIncidentEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "bansafe.incident" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BanSafeIncidentPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "BanSafeClaimPayload": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Claim id. Stable and quotable.", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f22" + }, + "incidentId": { + "type": "string", + "description": "The incident this claim was filed against.", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "phoneNumber": { + "type": "string", + "pattern": "^\\+[1-9]\\d{1,14}$", + "description": "The customer's own number in E.164 format.", + "example": "+15551234567" + }, + "status": { + "type": "string", + "enum": [ + "filed", + "under_review", + "approved", + "denied", + "paid", + "reversed" + ], + "description": "Where the claim sits. filed and under_review are open. approved means it was accepted, and with a zero amount that there was nothing to return. paid means the credits are on your balance. reversed means what Polymorfa knew about the ban changed afterwards and the credits were taken back." + }, + "verdict": { + "type": "string", + "enum": [ + "other_device", + "customer_conduct", + "shared_network", + "ours", + "inconclusive" + ], + "description": "What the ban was attributed to. other_device: another device on the account was sending. customer_conduct: Polymorfa was already restricting this number, or named the same serious problem for a week. shared_network: the number shared its connection with numbers that were being restricted. ours: nothing points at how the number was used. inconclusive: Polymorfa could not see enough of the window to say." + }, + "windowStart": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 start of the 30 days the refund covers.", + "example": "2026-08-07T14:03:12.000Z" + }, + "windowEnd": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 end of the window: the moment the ban started.", + "example": "2026-09-06T14:03:12.000Z" + }, + "measuredCents": { + "type": "integer", + "minimum": 0, + "description": "Credits this number consumed inside the window, in cents.", + "example": 1080 + }, + "capCents": { + "type": "integer", + "minimum": 0, + "description": "The most a claim on this number's plan can return, in cents.", + "example": 1080 + }, + "amountCents": { + "type": "integer", + "minimum": 0, + "description": "What this claim returns, in cents.", + "example": 1080 + }, + "summary": { + "type": "string", + "description": "One sentence describing the claim's state." + }, + "reason": { + "type": "string", + "description": "One sentence describing what the ban was attributed to." + }, + "decidedAt": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "ISO 8601 timestamp of the decision, or null while none was taken.", + "example": null + }, + "paidAt": { + "type": "string", + "nullable": true, + "format": "date-time", + "description": "ISO 8601 timestamp the credits landed, or null.", + "example": null + } + }, + "required": [ + "id", + "incidentId", + "phoneNumber", + "status", + "verdict", + "windowStart", + "windowEnd", + "measuredCents", + "capCents", + "amountCents", + "summary", + "reason", + "decidedAt", + "paidAt" + ], + "additionalProperties": false + }, + "BanSafeClaimEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "bansafe.claim" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/BanSafeClaimPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ], + "additionalProperties": false + }, + "MessageFailedPayload": { + "type": "object", + "properties": { + "to": { + "allOf": [ + { + "$ref": "#/components/schemas/IdentityRef" + }, + { + "description": "Recipient chat the send was attempted to" + } + ] + }, + "type": { + "type": "string", + "description": "Type of the attempted message (text, image, ...)", + "example": "text" + }, + "error": { + "type": "string", + "enum": [ + "invalid_recipient", + "session_not_connected", + "ack_timeout", + "send_failed", + "blocked_by_safety" + ], + "description": "Sanitized failure class", + "example": "send_failed" + }, + "code": { + "type": "string", + "description": "Stable machine-readable code from the API error envelope, present for classified safety refusals and an unknown send outcome", + "example": "bansafe_cold_blocked" + }, + "retryAfter": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Whole seconds to wait before retrying a paced send, exhausted allowance, or temporary allowance-accounting pause", + "example": 5 + }, + "timestamp": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the failure occurred", + "example": 1757161200 + } + }, + "required": [ + "to", + "type", + "error", + "timestamp" + ] + }, + "MessageFailedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "message.failed" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/MessageFailedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "TemplateStatusPayload": { + "type": "object", + "properties": { + "templateName": { + "type": "string", + "description": "Template name as registered with Meta", + "example": "order_update" + }, + "templateId": { + "type": "string", + "description": "Meta template id", + "example": "1234567890" + }, + "status": { + "type": "string", + "description": "New approval status: APPROVED, REJECTED, PAUSED, DISABLED, DELETED", + "example": "APPROVED" + }, + "category": { + "type": "string", + "description": "Template category (MARKETING, UTILITY, AUTHENTICATION)", + "example": "UTILITY" + }, + "reason": { + "type": "string", + "description": "Reason for the status change; empty unless REJECTED, PAUSED or DISABLED", + "example": "" + }, + "qualityRating": { + "type": "string", + "description": "Quality rating bucket reported by Meta (GREEN, YELLOW, RED)", + "example": "GREEN" + } + }, + "required": [ + "templateName", + "templateId", + "status", + "category", + "reason", + "qualityRating" + ] + }, + "TemplateStatusEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "template.status" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/TemplateStatusPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignPausedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "sentCount": { + "type": "integer", + "minimum": 0, + "description": "Recipients sent so far" + }, + "remainingCount": { + "type": "integer", + "minimum": 0, + "description": "Recipients still queued" + }, + "pausedAt": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the campaign paused", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "sentCount", + "remainingCount", + "pausedAt" + ] + }, + "CampaignPausedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.paused" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignPausedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignCompletedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "sentCount": { + "type": "integer", + "minimum": 0 + }, + "deliveredCount": { + "type": "integer", + "minimum": 0 + }, + "readCount": { + "type": "integer", + "minimum": 0 + }, + "failedCount": { + "type": "integer", + "minimum": 0 + }, + "skippedCount": { + "type": "integer", + "minimum": 0 + }, + "responseCount": { + "type": "integer", + "minimum": 0 + }, + "completedAt": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the last recipient settled", + "example": 1757161200 + }, + "durationMs": { + "type": "integer", + "minimum": 0, + "description": "Wall-clock duration from launch to completion, in milliseconds" + } + }, + "required": [ + "campaignId", + "sentCount", + "deliveredCount", + "readCount", + "failedCount", + "skippedCount", + "responseCount", + "completedAt", + "durationMs" + ] + }, + "CampaignCompletedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.completed" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignCompletedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignFailedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "reason": { + "type": "string", + "description": "Stable reason the campaign failed", + "example": "no_eligible_numbers" + }, + "failedAt": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the campaign failed", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "reason", + "failedAt" + ] + }, + "CampaignFailedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.failed" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignFailedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignRecipientSentPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "recipientId": { + "type": "string", + "description": "Campaign recipient id", + "example": "01936b2e-6a11-7d2e-8f4a-1c2b3d4e5f66" + }, + "phone": { + "type": "string", + "description": "Recipient phone number in E.164", + "example": "+14155550123" + }, + "sessionKey": { + "type": "string", + "description": "Sending number's session key", + "example": "sales-1" + }, + "externalMessageId": { + "type": "string", + "description": "WhatsApp message id of the delivered send", + "example": "3EB0A1B2C3D4E5F60718" + }, + "variantKey": { + "type": "string", + "description": "Content variant used for this recipient", + "example": "v1" + }, + "attempt": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true, + "description": "Attempt number that succeeded", + "example": 1 + } + }, + "required": [ + "campaignId", + "recipientId", + "phone", + "sessionKey", + "externalMessageId", + "variantKey", + "attempt" + ] + }, + "CampaignRecipientSentEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.recipient_sent" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignRecipientSentPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignRecipientFailedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "recipientId": { + "type": "string", + "description": "Campaign recipient id", + "example": "01936b2e-6a11-7d2e-8f4a-1c2b3d4e5f66" + }, + "phone": { + "type": "string", + "description": "Recipient phone number in E.164", + "example": "+14155550123" + }, + "attempts": { + "type": "integer", + "minimum": 0, + "description": "Attempts made before giving up" + }, + "error": { + "type": "string", + "description": "Sanitized failure class or stable code", + "example": "ack_timeout" + }, + "failedAt": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the recipient was marked failed", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "recipientId", + "phone", + "attempts", + "error", + "failedAt" + ] + }, + "CampaignRecipientFailedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.recipient_failed" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignRecipientFailedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignRecipientSkippedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "recipientId": { + "type": "string", + "description": "Campaign recipient id", + "example": "01936b2e-6a11-7d2e-8f4a-1c2b3d4e5f66" + }, + "phone": { + "type": "string", + "description": "Recipient phone number in E.164", + "example": "+14155550123" + }, + "reason": { + "type": "string", + "description": "Stable skip reason (skipped-optout, skipped-error, skipped-cold)", + "example": "skipped-cold" + }, + "skippedAt": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the recipient was skipped", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "recipientId", + "phone", + "reason", + "skippedAt" + ] + }, + "CampaignRecipientSkippedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.recipient_skipped" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignRecipientSkippedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignThrottledPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "sessionKey": { + "type": "string", + "description": "Sending number's session key", + "example": "sales-1" + }, + "reason": { + "type": "string", + "description": "Why sending was paced", + "example": "bansafe_throttled" + }, + "deferredCount": { + "type": "integer", + "minimum": 0, + "description": "Recipients deferred in this pass" + }, + "at": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds of the pacing decision", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "sessionKey", + "reason", + "deferredCount", + "at" + ] + }, + "CampaignThrottledEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.throttled" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignThrottledPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignCapReachedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "sessionKey": { + "type": "string", + "description": "Sending number's session key", + "example": "sales-1" + }, + "phone": { + "type": "string", + "description": "Sending number in E.164", + "example": "+14155550100" + }, + "capType": { + "type": "string", + "description": "Which cap was reached: hourly or daily", + "example": "daily" + }, + "capLimit": { + "type": "integer", + "minimum": 0, + "description": "The cap that was reached" + }, + "windowResetsAt": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the cap window resets", + "example": 1757161200 + }, + "at": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds of the decision", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "sessionKey", + "phone", + "capType", + "capLimit", + "windowResetsAt", + "at" + ] + }, + "CampaignCapReachedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.cap_reached" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignCapReachedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "CampaignColdBlockedPayload": { + "type": "object", + "properties": { + "campaignId": { + "type": "string", + "description": "Campaign id", + "example": "01936b2e-5f2a-7c1d-9a3e-8b4c2d1e0f11" + }, + "recipientId": { + "type": "string", + "description": "Campaign recipient id", + "example": "01936b2e-6a11-7d2e-8f4a-1c2b3d4e5f66" + }, + "phone": { + "type": "string", + "description": "Recipient phone number in E.164", + "example": "+14155550123" + }, + "surface": { + "type": "string", + "description": "Campaign surface", + "example": "whatsapp" + }, + "reason": { + "type": "string", + "description": "Stable hold reason", + "example": "bansafe_cold_held" + }, + "at": { + "type": "integer", + "minimum": 0, + "description": "Unix timestamp in seconds when the recipient was held", + "example": 1757161200 + } + }, + "required": [ + "campaignId", + "recipientId", + "phone", + "surface", + "reason", + "at" + ] + }, + "CampaignColdBlockedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique event identifier" + }, + "session": { + "type": "string", + "description": "Session that produced this event" + }, + "timestamp": { + "type": "string", + "description": "ISO 8601 timestamp" + }, + "event": { + "type": "string", + "enum": [ + "campaign.cold_blocked" + ], + "description": "Event type" + }, + "payload": { + "$ref": "#/components/schemas/CampaignColdBlockedPayload" + } + }, + "required": [ + "id", + "session", + "timestamp", + "event", + "payload" + ] + }, + "PingResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "ok" + } + }, + "required": [ + "status" + ] + }, + "HealthCheck": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "healthy" + }, + "error": { + "type": "string" + } + }, + "required": [ + "status" + ] + }, + "HealthResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "healthy" + }, + "checks": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/HealthCheck" + } + } + }, + "required": [ + "status", + "checks" + ] + }, + "VersionResponse": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "env": { + "type": "string" + }, + "apiVersion": { + "type": "string" + }, + "minSupportedVersion": { + "type": "string" + } + }, + "required": [ + "version", + "buildTime", + "env", + "apiVersion", + "minSupportedVersion" + ] + }, + "StatusResponse": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "uptime": { + "type": "string" + }, + "version": { + "type": "string" + }, + "env": { + "type": "string" + } + }, + "required": [ + "status", + "uptime", + "version", + "env" + ] + }, + "ErrorResponse": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Human-readable error message" + }, + "code": { + "type": "string", + "description": "Stable machine-readable error code, present on safety and entitlement refusals" + }, + "retryAfter": { + "type": "integer", + "description": "Seconds until the request can be retried, present on paced refusals and retryable service pauses" + }, + "docs": { + "type": "string", + "description": "URL to the documentation for this error" + } + }, + "required": [ + "error" + ] + }, + "SuccessResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "message": { + "type": "string" + } + }, + "required": [ + "success" + ] + }, + "ClientToken": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Client token with pmfa_ct_ prefix" + }, + "expiresAt": { + "type": "string" + } + }, + "required": [ + "token", + "expiresAt" + ] + }, + "MintClientTokenResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ClientToken" + } + }, + "required": [ + "success", + "data" + ] + }, + "MintClientTokenRequest": { + "type": "object", + "properties": { + "session": { + "type": "string", + "minLength": 1 + }, + "ephemeralId": { + "type": "string", + "minLength": 1 + }, + "ttlSeconds": { + "type": "integer" + } + }, + "required": [ + "session", + "ephemeralId" + ] + }, + "ClientRules": { + "type": "object", + "properties": { + "actions": { + "type": "array", + "items": { + "type": "string" + } + }, + "recipientMode": { + "type": "string" + }, + "verifiedJids": { + "type": "array", + "items": { + "type": "string" + } + }, + "rateLimits": { + "type": "object", + "properties": { + "perMinute": { + "type": "integer", + "minimum": 0 + }, + "perDay": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "required": [ + "actions", + "recipientMode" + ] + }, + "GetClientRulesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ClientRules" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetClientRulesRequest": { + "type": "object", + "properties": { + "recipientMode": { + "type": "string" + }, + "allowedActions": { + "type": "string", + "default": "" + }, + "rateLimit": { + "type": "integer", + "default": 0 + }, + "maxDaily": { + "type": "integer", + "default": 0 + }, + "allowedOrigins": { + "type": "string", + "default": "" + }, + "enabled": { + "type": "boolean" + }, + "maxConcurrency": { + "type": "integer", + "minimum": 0, + "default": 0 + }, + "allowedNumber": { + "type": "string", + "default": "" + }, + "maxSetupsPerMinute": { + "type": "integer", + "minimum": 0, + "maximum": 600, + "default": 0 + } + }, + "required": [ + "recipientMode", + "enabled" + ] + }, + "Session": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Canonical per-org session identifier. Use this in /messaging/sessions/{session}/* paths." + }, + "name": { + "type": "string", + "description": "Display label, or the session identifier when no label is set." + }, + "tenantId": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "linked_device", + "cloud_api" + ], + "description": "How the session connects to WhatsApp. 'linked_device' pairs as a WhatsApp linked device; 'cloud_api' uses the Meta Cloud API. Immutable after create." + }, + "testMode": { + "type": "boolean", + "description": "Whether this session was created as a simulated testing number." + }, + "status": { + "type": "string", + "description": "Current status: CONNECTING, CONNECTED, or DISCONNECTED" + }, + "statusReason": { + "type": "string" + }, + "config": { + "type": "object", + "properties": { + "historySync": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "metadata_only", + "deliver" + ] + }, + "requestFull": { + "type": "boolean" + } + }, + "required": [ + "mode", + "requestFull" + ] + } + } + }, + "createdAt": { + "type": "string" + }, + "updatedAt": { + "type": "string" + } + }, + "required": [ + "sessionId", + "name", + "tenantId", + "type", + "testMode", + "status", + "config", + "createdAt", + "updatedAt" + ] + }, + "ListSessionsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Session" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "SessionOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/Session" + }, + { + "type": "object", + "properties": {} + } + ] + }, + "CreateSessionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SessionOperation" + } + }, + "required": [ + "success", + "data" + ] + }, + "CloudApiCredentials": { + "type": "object", + "properties": { + "phoneNumberId": { + "type": "string", + "minLength": 1 + }, + "wabaId": { + "type": "string", + "minLength": 1 + }, + "businessAccountId": { + "type": "string" + }, + "appId": { + "type": "string", + "minLength": 1 + }, + "appSecret": { + "type": "string", + "minLength": 1 + }, + "systemUserToken": { + "type": "string", + "minLength": 1 + }, + "webhookVerifyToken": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "phoneNumberId", + "wabaId", + "appId", + "appSecret", + "systemUserToken", + "webhookVerifyToken" + ], + "description": "Credentials required when type is cloud_api. Stored encrypted." + }, + "HistorySyncPolicy": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "metadata_only", + "deliver" + ], + "default": "metadata_only" + }, + "requestFull": { + "type": "boolean", + "default": false + } + }, + "additionalProperties": false, + "description": "History processing for linked-device sessions. Defaults to metadata-only processing." + }, + "SessionConfig": { + "type": "object", + "properties": { + "historySync": { + "$ref": "#/components/schemas/HistorySyncPolicy" + } + }, + "additionalProperties": false + }, + "CreateSessionRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Optional display label. The server generates the session identifier." + }, + "startOnConnect": { + "type": "boolean", + "default": false, + "description": "Start connecting immediately after creation. Pairing or credentials are still required." + }, + "type": { + "type": "string", + "enum": [ + "linked_device", + "cloud_api" + ], + "default": "linked_device", + "description": "Connection type. Immutable after creation." + }, + "testMode": { + "type": "boolean", + "default": false, + "description": "Create a simulated testing session." + }, + "cloudApi": { + "$ref": "#/components/schemas/CloudApiCredentials" + }, + "config": { + "$ref": "#/components/schemas/SessionConfig" + } + }, + "additionalProperties": false + }, + "GetSessionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Session" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateSessionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Session" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateSessionRequest": { + "type": "object", + "properties": { + "config": { + "type": "object", + "additionalProperties": true + }, + "historySync": { + "$ref": "#/components/schemas/HistorySyncPolicy" + } + } + }, + "OperationAccepted": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "message": { + "type": "string" + }, + "immediate": { + "type": "boolean" + } + }, + "required": [ + "success", + "message" + ] + }, + "WhatsAppAccount": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable account ID when supplied by the connection." + }, + "phoneNumber": { + "type": "string" + }, + "pushName": { + "type": "string" + }, + "businessName": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "profilePicUrl": { + "type": "string" + } + }, + "required": [ + "pushName" + ] + }, + "GetSessionAccountResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/WhatsAppAccount" + } + }, + "required": [ + "success", + "data" + ] + }, + "HandoffKeysResponse": { + "type": "object", + "properties": { + "runnerPublicKeyB64": { + "type": "string", + "description": "Curve25519 public key the customer must seal their snapshot to. Base64 (URL-safe, no padding)." + }, + "handoffId": { + "type": "string" + } + }, + "required": [ + "runnerPublicKeyB64", + "handoffId" + ] + }, + "HandoffKeysSuccess": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/HandoffKeysResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "HandoffImportSuccess": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SuccessResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "HandoffImportRequest": { + "type": "object", + "properties": { + "handoffId": { + "type": "string", + "description": "Round-trip id returned by POST /handoff-keys." + }, + "sealedEnvelopeB64": { + "type": "string", + "description": "Sealed-box envelope (ephemeral_pub(32) || ciphertext) wrapping the customer's SignalStoreSnapshot. Base64." + }, + "snapshotHashHex": { + "type": "string", + "description": "SHA-256 of the unsealed snapshot JSON, hex-encoded. The runner verifies after decrypt before flipping bartenderMode." + } + }, + "required": [ + "handoffId", + "sealedEnvelopeB64", + "snapshotHashHex" + ] + }, + "UploadAppStateKeysSuccess": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SuccessResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "UploadAppStateKeysRequest": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "type": "object", + "properties": { + "keyId": { + "type": "string", + "description": "Base64-encoded AppStateSyncKey id (URL-safe-no-pad)." + }, + "keyB64": { + "type": "string", + "description": "Base64-encoded 32-byte symmetric key bytes." + }, + "fingerprintB64": { + "type": "string", + "description": "Base64-encoded WA fingerprint blob (optional)." + }, + "timestamp": { + "type": "number", + "description": "Unix-seconds timestamp WA stamped on the key." + } + }, + "required": [ + "keyId", + "keyB64", + "timestamp" + ] + } + }, + "upgradeTo": { + "type": "string", + "enum": [ + "passthrough_plus" + ], + "description": "When set, atomically flips sessions.config.bartenderMode → passthrough_plus after the keys persist. Eliminates the window where mode is set but no keys are staged." + } + }, + "required": [ + "keys" + ] + }, + "HandoffAckSuccess": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SuccessResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "HandoffAckRequest": { + "type": "object", + "properties": { + "handoffId": { + "type": "string" + }, + "snapshotHashHex": { + "type": "string", + "description": "SHA-256 of the snapshot the customer received via mode.handoff_export. API verifies this matches what the runner exported before flipping bartenderMode." + } + }, + "required": [ + "handoffId", + "snapshotHashHex" + ] + }, + "QRResponse": { + "type": "object", + "properties": { + "qr": { + "type": "string", + "description": "QR code data to encode into a scannable image" + }, + "event": { + "type": "string", + "description": "QR channel event (e.g. success, timeout)" + } + } + }, + "GetQRCodeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/QRResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "PairCodeResponse": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Numeric pairing code for device linking" + } + }, + "required": [ + "code" + ] + }, + "RequestPairCodeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/PairCodeResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "PairCodeRequest": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "phone" + ] + }, + "ConversationIdentifier": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable conversation ID. Linked Device users use pmfa_lid_, groups use pmfa_gid_, bots use pmfa_botid_, and Cloud users use their business-scoped ID.", + "example": "pmfa_lid_123456789" + }, + "phoneNumber": { + "type": "string", + "pattern": "^\\+[1-9]\\d{1,14}$", + "description": "E.164 phone number. Supply it alone or alongside id; id selects the conversation when both are present.", + "example": "+15550001111" + } + }, + "additionalProperties": false, + "description": "ConversationIdentifier identified by an ID, an E.164 phone number, or both. At least one is required. When both are supplied, the ID selects the conversation and phoneNumber is an alias. User IDs use pmfa_lid_, group IDs use pmfa_gid_, and bot IDs use pmfa_botid_. Cloud API user IDs are business-scoped.", + "anyOf": [ + { + "required": [ + "id" + ] + }, + { + "required": [ + "phoneNumber" + ] + } + ] + }, + "SentMessage": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Upstream acceptance status. Delivery and read receipts arrive separately." + }, + "type": { + "type": "string" + }, + "content": { + "$ref": "#/components/schemas/MessageContent" + }, + "mediaId": { + "type": "string" + } + }, + "required": [ + "id", + "conversation", + "timestamp", + "status", + "type", + "content" + ] + }, + "SendMessageResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SentMessage" + } + }, + "required": [ + "success", + "data" + ] + }, + "AsyncAcceptedResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "requestId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "requestId" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "PublicError": { + "type": "object", + "properties": { + "error": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "invalid_request_error", + "authentication_error", + "permission_error", + "conflict_error", + "rate_limit_error", + "api_error", + "upstream_error" + ] + }, + "code": { + "type": "string", + "enum": [ + "invalid_parameter", + "invalid_credential", + "entitlement_required", + "method_not_allowed", + "permission_denied", + "missing_scope", + "resource_not_found", + "media_fetch_failed", + "resource_gone", + "state_conflict", + "rate_limit_exceeded", + "internal_error", + "operation_not_supported", + "upstream_failure", + "service_unavailable", + "credential_verification_unavailable", + "session_not_ready", + "command_dispatch_failed", + "result_unknown" + ] + }, + "message": { + "type": "string" + }, + "param": { + "type": "string", + "nullable": true + } + }, + "required": [ + "type", + "code", + "message", + "param" + ] + }, + "data": { + "type": "string", + "nullable": true, + "enum": [ + null + ], + "description": "Always null for a failed request." + }, + "docs": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "error", + "data", + "docs" + ] + }, + "QuotedMessage": { + "type": "object", + "properties": { + "messageId": { + "type": "string" + }, + "participant": { + "type": "string" + }, + "type": { + "type": "string" + }, + "text": { + "type": "string" + } + }, + "required": [ + "messageId", + "participant" + ], + "description": "Message being replied to." + }, + "MessageContent": { + "description": "Exactly one message kind: text, image, location, or another supported content field.", + "oneOf": [ + { + "type": "object", + "properties": { + "text": { + "type": "string", + "minLength": 1, + "description": "Text to send." + } + }, + "required": [ + "text" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "image": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL of the media to send. Specify this or base64." + }, + "base64": { + "type": "string", + "minLength": 1, + "description": "Base64-encoded media bytes. Specify this or url." + }, + "mimeType": { + "type": "string", + "description": "MIME type of the media." + }, + "caption": { + "type": "string", + "description": "Caption sent with the media." + } + }, + "additionalProperties": false + } + }, + "required": [ + "image" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "video": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL of the media to send. Specify this or base64." + }, + "base64": { + "type": "string", + "minLength": 1, + "description": "Base64-encoded media bytes. Specify this or url." + }, + "mimeType": { + "type": "string", + "description": "MIME type of the media." + }, + "caption": { + "type": "string", + "description": "Caption sent with the media." + } + }, + "additionalProperties": false + } + }, + "required": [ + "video" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "file": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL of the media to send. Specify this or base64." + }, + "base64": { + "type": "string", + "minLength": 1, + "description": "Base64-encoded media bytes. Specify this or url." + }, + "mimeType": { + "type": "string", + "description": "MIME type of the media." + }, + "caption": { + "type": "string", + "description": "Caption sent with the media." + }, + "filename": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "required": [ + "file" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "voice": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri", + "description": "URL of the media to send. Specify this or base64." + }, + "base64": { + "type": "string", + "minLength": 1, + "description": "Base64-encoded media bytes. Specify this or url." + }, + "mimeType": { + "type": "string", + "description": "MIME type of the media." + }, + "caption": { + "type": "string", + "description": "Caption sent with the media." + }, + "ptt": { + "type": "boolean" + } + }, + "additionalProperties": false + } + }, + "required": [ + "voice" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "location": { + "type": "object", + "properties": { + "lat": { + "type": "number", + "minimum": -90, + "maximum": 90, + "description": "Latitude in decimal degrees." + }, + "long": { + "type": "number", + "minimum": -180, + "maximum": 180, + "description": "Longitude in decimal degrees." + }, + "address": { + "type": "string", + "description": "Display address for the location." + } + }, + "required": [ + "lat", + "long" + ], + "additionalProperties": false + } + }, + "required": [ + "location" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "poll": { + "type": "object", + "properties": { + "title": { + "type": "string", + "minLength": 1 + }, + "options": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 2 + }, + "multiSelect": { + "type": "boolean" + } + }, + "required": [ + "title", + "options" + ], + "additionalProperties": false + } + }, + "required": [ + "poll" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "contact": { + "type": "object", + "properties": { + "vcard": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "vcard" + ], + "additionalProperties": false + } + }, + "required": [ + "contact" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "requestPhoneNumber": { + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "required": [ + "requestPhoneNumber" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "product": { + "type": "object", + "properties": { + "businessOwnerJid": { + "type": "string", + "pattern": "^\\d+@s\\.whatsapp\\.net$" + }, + "id": { + "type": "string", + "minLength": 1 + }, + "title": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 0 + }, + "currencyCode": { + "type": "string", + "pattern": "^[A-Z]{3}$" + }, + "priceAmount1000": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "salePriceAmount1000": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "retailerId": { + "type": "string", + "minLength": 0 + }, + "url": { + "type": "string", + "maxLength": 2048, + "format": "uri" + }, + "imageCount": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "image": { + "type": "object", + "properties": { + "url": { + "type": "string", + "maxLength": 4096, + "format": "uri" + }, + "base64": { + "type": "string", + "maxLength": 87384 + }, + "mimeType": { + "type": "string", + "minLength": 0 + } + } + }, + "body": { + "type": "string", + "minLength": 0 + }, + "footer": { + "type": "string", + "minLength": 0 + } + }, + "required": [ + "businessOwnerJid", + "id", + "title", + "currencyCode", + "priceAmount1000" + ] + } + }, + "required": [ + "product" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "productList": { + "type": "object", + "properties": { + "businessOwnerJid": { + "type": "string", + "pattern": "^\\d+@s\\.whatsapp\\.net$" + }, + "title": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 0 + }, + "buttonText": { + "type": "string", + "minLength": 1 + }, + "footer": { + "type": "string", + "minLength": 0 + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "minLength": 0 + }, + "productIds": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 1, + "maxItems": 30 + } + }, + "required": [ + "productIds" + ] + }, + "minItems": 1, + "maxItems": 10 + } + }, + "required": [ + "businessOwnerJid", + "title", + "buttonText", + "sections" + ] + } + }, + "required": [ + "productList" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "order": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 1 + }, + "thumbnailBase64": { + "type": "string", + "maxLength": 87384 + }, + "itemCount": { + "type": "integer", + "minimum": 1, + "maximum": 100 + }, + "status": { + "type": "string", + "enum": [ + "inquiry", + "accepted", + "declined" + ] + }, + "message": { + "type": "string", + "minLength": 0 + }, + "title": { + "type": "string", + "minLength": 0 + }, + "sellerJid": { + "type": "string", + "pattern": "^\\d+@s\\.whatsapp\\.net$" + }, + "token": { + "type": "string", + "minLength": 0 + }, + "totalAmount1000": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "totalCurrencyCode": { + "type": "string", + "pattern": "^[A-Z]{3}$" + }, + "catalogType": { + "type": "string", + "minLength": 0 + } + }, + "required": [ + "id", + "itemCount", + "status", + "sellerJid", + "totalAmount1000", + "totalCurrencyCode" + ] + } + }, + "required": [ + "order" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "list": { + "type": "object", + "properties": { + "title": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 0 + }, + "buttonText": { + "type": "string", + "minLength": 1 + }, + "footer": { + "type": "string", + "minLength": 0 + }, + "sections": { + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "type": "string", + "minLength": 0 + }, + "rows": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 1 + }, + "title": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 0 + } + }, + "required": [ + "id", + "title" + ] + }, + "minItems": 1, + "maxItems": 30 + } + }, + "required": [ + "rows" + ] + }, + "minItems": 1, + "maxItems": 10 + } + }, + "required": [ + "title", + "buttonText", + "sections" + ] + } + }, + "required": [ + "list" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "buttons": { + "type": "object", + "properties": { + "title": { + "type": "string", + "minLength": 0 + }, + "body": { + "type": "string", + "minLength": 1 + }, + "footer": { + "type": "string", + "minLength": 0 + }, + "buttons": { + "type": "array", + "items": { + "oneOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "url" + ] + }, + "text": { + "type": "string", + "minLength": 1 + }, + "url": { + "type": "string", + "maxLength": 2048, + "format": "uri" + } + }, + "required": [ + "type", + "text", + "url" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "call" + ] + }, + "text": { + "type": "string", + "minLength": 1 + }, + "phoneNumber": { + "type": "string", + "pattern": "^\\+?\\d{6,20}$" + } + }, + "required": [ + "type", + "text", + "phoneNumber" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "reply" + ] + }, + "text": { + "type": "string", + "minLength": 1 + }, + "id": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "type", + "text", + "id" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "copy" + ] + }, + "text": { + "type": "string", + "minLength": 1 + }, + "copyCode": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "type", + "text", + "copyCode" + ] + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "catalog" + ] + }, + "text": { + "type": "string", + "minLength": 1 + }, + "businessPhoneNumber": { + "type": "string", + "pattern": "^\\+?\\d{6,20}$" + }, + "catalogProductId": { + "type": "string", + "minLength": 0 + } + }, + "required": [ + "type", + "text", + "businessPhoneNumber" + ] + } + ] + }, + "minItems": 1, + "maxItems": 3 + } + }, + "required": [ + "body", + "buttons" + ] + } + }, + "required": [ + "buttons" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "addressMessage": { + "type": "object", + "properties": { + "body": { + "type": "string", + "minLength": 1 + }, + "buttonText": { + "type": "string", + "minLength": 1 + }, + "footer": { + "type": "string", + "minLength": 0 + }, + "country": { + "type": "string", + "pattern": "^[A-Z]{2}$" + } + }, + "required": [ + "body" + ] + } + }, + "required": [ + "addressMessage" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "flow": { + "type": "object", + "properties": { + "body": { + "type": "string", + "minLength": 1 + }, + "buttonText": { + "type": "string", + "minLength": 1 + }, + "footer": { + "type": "string", + "minLength": 0 + }, + "id": { + "type": "string", + "minLength": 1 + }, + "token": { + "type": "string", + "minLength": 1 + }, + "action": { + "type": "string", + "enum": [ + "navigate", + "data_exchange" + ] + }, + "screen": { + "type": "string", + "minLength": 0 + }, + "dataJson": { + "type": "string", + "minLength": 0 + } + }, + "required": [ + "body", + "buttonText", + "id", + "token", + "action" + ], + "oneOf": [ + { + "properties": { + "action": { + "enum": [ + "navigate" + ] + } + }, + "required": [ + "screen" + ] + }, + { + "properties": { + "action": { + "enum": [ + "data_exchange" + ] + } + }, + "not": { + "anyOf": [ + { + "required": [ + "screen" + ] + }, + { + "required": [ + "dataJson" + ] + } + ] + } + } + ] + } + }, + "required": [ + "flow" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "template": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "language": { + "type": "string", + "minLength": 2 + }, + "components": { + "type": "array", + "items": {} + } + }, + "required": [ + "name", + "language" + ], + "additionalProperties": false + } + }, + "required": [ + "template" + ], + "additionalProperties": false + } + ] + }, + "SendMessageRequest": { + "type": "object", + "properties": { + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "isForwarded": { + "type": "boolean", + "description": "Mark this message as forwarded." + }, + "mentions": { + "type": "array", + "items": { + "type": "string", + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "description": "User IDs to mention in this message." + }, + "quotedMessage": { + "$ref": "#/components/schemas/QuotedMessage" + }, + "content": { + "$ref": "#/components/schemas/MessageContent" + } + }, + "required": [ + "conversation", + "content" + ], + "additionalProperties": false, + "description": "Specify conversation and content containing exactly one message kind. Shared options remain outside content." + }, + "MessageActionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "status": { + "type": "string" + } + }, + "required": [ + "status" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "SeenRequest": { + "type": "object", + "properties": { + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "id": { + "type": "string", + "minLength": 1 + }, + "participant": { + "type": "string", + "description": "Sender ID or phone number of the message being marked read. Required by WhatsApp for group chats; when omitted the sender is resolved from the message id." + } + }, + "required": [ + "conversation", + "id" + ], + "additionalProperties": false + }, + "TypingRequest": { + "type": "object", + "properties": { + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "state": { + "type": "string", + "enum": [ + "typing", + "recording", + "paused" + ] + } + }, + "required": [ + "conversation", + "state" + ], + "additionalProperties": false + }, + "MessageReceipt": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Upstream acceptance status. Delivery and read receipts arrive separately." + } + }, + "required": [ + "id", + "conversation", + "timestamp", + "status" + ] + }, + "SendReactionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/MessageReceipt" + } + }, + "required": [ + "success", + "data" + ] + }, + "ReactRequest": { + "type": "object", + "properties": { + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "id": { + "type": "string", + "minLength": 1 + }, + "reaction": { + "type": "string" + } + }, + "required": [ + "conversation", + "id", + "reaction" + ], + "additionalProperties": false + }, + "StarRequest": { + "type": "object", + "properties": { + "conversation": { + "$ref": "#/components/schemas/ConversationIdentifier" + }, + "id": { + "type": "string", + "minLength": 1 + }, + "star": { + "type": "boolean" + }, + "fromMe": { + "type": "boolean" + }, + "sender": { + "type": "string" + } + }, + "required": [ + "conversation", + "id", + "star" + ], + "additionalProperties": false + }, + "EditMessageRequest": { + "type": "object", + "properties": { + "text": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "text" + ] + }, + "DisappearingTimerRequest": { + "type": "object", + "properties": { + "durationSeconds": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 86400 + ] + }, + { + "type": "number", + "enum": [ + 604800 + ] + }, + { + "type": "number", + "enum": [ + 7776000 + ] + } + ] + } + }, + "required": [ + "durationSeconds" + ] + }, + "RejectCallRequest": { + "type": "object", + "properties": { + "from": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$", + "description": "ID of the incoming caller" + } + }, + "required": [ + "from" + ] + }, + "ICEServer": { + "type": "object", + "properties": { + "urls": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "username": { + "type": "string" + }, + "credential": { + "type": "string" + } + }, + "required": [ + "urls" + ] + }, + "SDPAnswer": { + "type": "object", + "properties": { + "sdp": { + "type": "string" + }, + "iceServers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ICEServer" + } + } + }, + "required": [ + "sdp", + "iceServers" + ] + }, + "VoipOfferResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SDPAnswer" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipOfferRequest": { + "type": "object", + "properties": { + "sdp": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "sdp" + ] + }, + "VoipRenegotiateResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SDPAnswer" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipRenegotiateRequest": { + "type": "object", + "properties": { + "sdp": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "sdp" + ] + }, + "VoipSocketTicket": { + "type": "object", + "properties": { + "ticket": { + "type": "string" + }, + "expiresAt": { + "type": "number" + }, + "url": { + "type": "string" + } + }, + "required": [ + "ticket", + "expiresAt", + "url" + ] + }, + "VoipSocketTicketResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipSocketTicket" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipSocketTicketRequest": { + "type": "object", + "properties": { + "session": { + "type": "string", + "minLength": 1 + } + } + }, + "VoipAgentToken": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "expiresAt": { + "type": "number" + } + }, + "required": [ + "token", + "expiresAt" + ] + }, + "VoipAgentTokenResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipAgentToken" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipAgentTokenRequest": { + "type": "object", + "properties": { + "ttlSeconds": { + "type": "integer", + "minimum": 1, + "maximum": 3600 + } + } + }, + "VoipPlacedCall": { + "type": "object", + "properties": { + "callId": { + "type": "string" + }, + "session": { + "type": "string" + }, + "video": { + "type": "boolean" + } + }, + "required": [ + "callId", + "session", + "video" + ] + }, + "VoipPlacedCallResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipPlacedCall" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipPlaceCallRequest": { + "type": "object", + "properties": { + "session": { + "type": "string", + "minLength": 1, + "example": "support" + }, + "to": { + "type": "string", + "pattern": "^(?:\\+[1-9]\\d{1,14}|pmfa_(?:lid|botid)_[1-9]\\d*)$", + "example": "+15550100" + }, + "video": { + "type": "boolean" + } + }, + "required": [ + "to" + ] + }, + "VoipAcceptCallRequest": { + "type": "object", + "properties": { + "video": { + "type": "boolean" + } + } + }, + "VoipParticipant": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "handle": { + "type": "string" + }, + "audioMuted": { + "type": "boolean" + }, + "video": { + "type": "boolean" + }, + "state": { + "type": "string", + "enum": [ + "invited", + "ringing", + "connected", + "left" + ] + } + }, + "required": [ + "id", + "handle", + "audioMuted", + "video", + "state" + ] + }, + "VoipAddParticipantResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipParticipant" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipAddParticipantRequest": { + "type": "object", + "properties": { + "to": { + "type": "string", + "pattern": "^(?:\\+[1-9]\\d{1,14}|pmfa_(?:lid|botid)_[1-9]\\d*)$", + "example": "+15550100" + } + }, + "required": [ + "to" + ] + }, + "VoipModeResponse": { + "type": "object", + "properties": { + "session": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "browser", + "agent", + "sdk" + ] + } + }, + "required": [ + "session", + "mode" + ] + }, + "VoipModeResult": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipModeResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipModeRequest": { + "type": "object", + "properties": { + "session": { + "type": "string", + "minLength": 1, + "example": "support" + }, + "mode": { + "type": "string", + "enum": [ + "browser", + "agent", + "sdk" + ] + } + }, + "required": [ + "mode" + ] + }, + "VoipCandidateRequest": { + "type": "object", + "properties": { + "candidate": { + "type": "string" + }, + "sdpMid": { + "type": "string" + }, + "sdpMLineIndex": { + "type": "integer" + } + }, + "required": [ + "candidate" + ] + }, + "TrickleCandidate": { + "type": "object", + "properties": { + "candidate": { + "type": "string" + }, + "sdpMid": { + "type": "string" + }, + "sdpMLineIndex": { + "type": "integer" + } + }, + "required": [ + "candidate" + ] + }, + "VoipCandidatesResponse": { + "type": "object", + "properties": { + "candidates": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TrickleCandidate" + } + } + }, + "required": [ + "candidates" + ] + }, + "VoipCandidatesEnvelope": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipCandidatesResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipToken": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "expiresAt": { + "type": "number" + } + }, + "required": [ + "token", + "expiresAt" + ] + }, + "VoipTokenResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/VoipToken" + } + }, + "required": [ + "success", + "data" + ] + }, + "VoipTokenRequest": { + "type": "object", + "properties": { + "session": { + "type": "string", + "minLength": 1 + }, + "ephemeralId": { + "type": "string", + "minLength": 1 + }, + "ttlSeconds": { + "type": "integer" + } + }, + "required": [ + "session", + "ephemeralId" + ] + }, + "Participant": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "isAdmin": { + "type": "boolean" + }, + "isSuperAdmin": { + "type": "boolean" + } + }, + "required": [ + "id", + "isAdmin", + "isSuperAdmin" + ] + }, + "Group": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Group ID, such as pmfa_gid_120363000000001" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "ownerId": { + "type": "string" + }, + "createdAt": { + "type": "number", + "description": "Unix timestamp in seconds" + }, + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Participant" + } + } + }, + "required": [ + "id", + "name", + "description", + "ownerId", + "createdAt", + "participants" + ] + }, + "ListGroupsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Group" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateGroupResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Group" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateGroupRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "participants": { + "type": "array", + "items": { + "type": "string", + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "minItems": 1 + } + }, + "required": [ + "name", + "participants" + ] + }, + "GroupInviteInfo": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "subject": { + "type": "string" + }, + "creatorId": { + "type": "string" + }, + "createdAt": { + "type": "number" + }, + "size": { + "type": "number" + }, + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Participant" + } + } + }, + "required": [ + "id", + "subject", + "creatorId", + "createdAt", + "size", + "participants" + ] + }, + "GetGroupJoinInfoResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/GroupInviteInfo" + } + }, + "required": [ + "success", + "data" + ] + }, + "JoinGroupRequest": { + "type": "object", + "properties": { + "code": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "code" + ] + }, + "GetGroupResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Group" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetGroupFieldRequest": { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "InviteCodeResponse": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Group invite code" + } + }, + "required": [ + "code" + ] + }, + "GetGroupInviteCodeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/InviteCodeResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "RevokeGroupInviteCodeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/InviteCodeResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "GetGroupParticipantsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Participant" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "GroupParticipantsRequest": { + "type": "object", + "properties": { + "participants": { + "type": "array", + "items": { + "type": "string", + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "minItems": 1 + } + }, + "required": [ + "participants" + ] + }, + "SetGroupPictureRequest": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "base64": { + "type": "string" + } + } + }, + "GroupAdminOnlySettingRequest": { + "type": "object", + "properties": { + "adminsOnly": { + "type": "boolean" + } + }, + "required": [ + "adminsOnly" + ] + }, + "GroupMemberAddModeRequest": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "admin_add", + "all_member_add" + ] + } + }, + "required": [ + "mode" + ] + }, + "GroupJoinApprovalRequest": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + } + }, + "required": [ + "required" + ] + }, + "Contact": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "pushName": { + "type": "string" + }, + "businessName": { + "type": "string" + }, + "profileUrl": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "pushName" + ] + }, + "ListContactsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Contact" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "CheckContactResult": { + "type": "object", + "properties": { + "exists": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "exists" + ] + }, + "CheckContactsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CheckContactResult" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "Blocklist": { + "type": "object", + "properties": { + "hash": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + } + } + } + } + }, + "required": [ + "hash", + "contacts" + ] + }, + "GetBlocklistResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Blocklist" + } + }, + "required": [ + "success", + "data" + ] + }, + "GetContactResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Contact" + } + }, + "required": [ + "success", + "data" + ] + }, + "ProfilePictureResponse": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "HTTPS URL of the profile picture" + } + }, + "required": [ + "url" + ] + }, + "GetContactPictureResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProfilePictureResponse" + } + }, + "required": [ + "success", + "data" + ] + }, + "UserInfo": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "status": { + "type": "string" + }, + "pictureId": { + "type": "string" + }, + "verifiedName": { + "type": "string" + }, + "devices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "device": { + "type": "integer" + } + }, + "required": [ + "device" + ] + } + } + }, + "required": [ + "id", + "status", + "pictureId", + "verifiedName", + "devices" + ] + }, + "GetUserInfoResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/UserInfo" + } + }, + "required": [ + "success", + "data" + ] + }, + "GetUserDevicesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "device": { + "type": "integer" + } + }, + "required": [ + "device" + ] + } + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessProfile": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "address": { + "type": "string" + }, + "email": { + "type": "string" + }, + "description": { + "type": "string" + }, + "websites": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + }, + "coverPhotoId": { + "type": "string" + }, + "categories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + } + }, + "options": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "hoursTimeZone": { + "type": "string" + }, + "hours": { + "type": "array", + "items": { + "type": "object", + "properties": { + "dayOfWeek": { + "type": "string" + }, + "mode": { + "type": "string" + }, + "openTime": { + "type": "string" + }, + "closeTime": { + "type": "string" + } + }, + "required": [ + "dayOfWeek", + "mode", + "openTime", + "closeTime" + ] + } + } + }, + "required": [ + "id", + "address", + "email", + "description", + "websites", + "coverPhotoId", + "categories", + "options", + "hoursTimeZone", + "hours" + ] + }, + "GetBusinessProfileResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessProfile" + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessLinkedAccounts": { + "type": "object", + "properties": { + "facebookPage": { + "type": "object", + "properties": { + "hasActiveCTWAAd": { + "type": "boolean" + }, + "hasCreatedAd": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "profileSync": { + "type": "string", + "enum": [ + "disable", + "import" + ] + }, + "profilePictureUrl": { + "type": "string", + "format": "uri" + }, + "showOnProfile": { + "type": "boolean" + }, + "whatsAppAsPageButton": { + "type": "boolean" + } + }, + "required": [ + "hasActiveCTWAAd", + "hasCreatedAd", + "id", + "displayName", + "profilePictureUrl", + "showOnProfile", + "whatsAppAsPageButton" + ] + }, + "facebookBusiness": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "catalogId": { + "type": "string" + }, + "catalogState": { + "type": "string", + "enum": [ + "disable", + "import" + ] + } + }, + "required": [ + "id", + "displayName" + ] + }, + "instagramProfessional": { + "type": "object", + "properties": { + "handle": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "profilePictureUrl": { + "type": "string", + "format": "uri" + }, + "showOnProfile": { + "type": "boolean" + } + }, + "required": [ + "handle", + "displayName", + "profilePictureUrl", + "showOnProfile" + ] + }, + "whatsAppAdIdentity": { + "type": "object", + "properties": { + "hasActiveCTWAAd": { + "type": "boolean" + }, + "hasCreatedAd": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "hasActiveCTWAAd", + "hasCreatedAd", + "id" + ] + } + } + }, + "GetBusinessLinkedAccountsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessLinkedAccounts" + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessEligibility": { + "type": "object", + "properties": { + "features": { + "type": "array", + "items": { + "type": "object", + "properties": { + "feature": { + "type": "string", + "enum": [ + "meta_verified", + "marketing_messages", + "genai", + "genai_image", + "meta_one", + "bb_pro" + ] + }, + "status": { + "type": "string" + }, + "expiration": { + "type": "integer" + }, + "additionalParams": { + "type": "string" + }, + "showPrivacyInterstitialToNewUsers": { + "type": "boolean" + }, + "v1Enabled": { + "type": "boolean" + } + }, + "required": [ + "feature", + "status" + ] + }, + "maxItems": 6 + } + }, + "required": [ + "features" + ] + }, + "GetBusinessEligibilityResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessEligibility" + } + }, + "required": [ + "success", + "data" + ] + }, + "GetOwnBusinessProfileResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessProfile" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateBusinessProfileResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "status": { + "type": "string" + } + }, + "required": [ + "status" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessProfileUpdateRequest": { + "type": "object", + "properties": { + "address": { + "type": "string", + "maxLength": 512 + }, + "email": { + "anyOf": [ + { + "type": "string", + "enum": [ + "" + ] + }, + { + "type": "string", + "maxLength": 320, + "format": "email" + } + ] + }, + "description": { + "type": "string", + "maxLength": 1024 + }, + "websites": { + "type": "array", + "items": { + "type": "string", + "maxLength": 2048, + "format": "uri" + }, + "minItems": 1, + "maxItems": 2 + }, + "hours": { + "type": "object", + "properties": { + "timeZone": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "days": { + "type": "array", + "items": { + "type": "object", + "properties": { + "dayOfWeek": { + "type": "string", + "enum": [ + "sun", + "mon", + "tue", + "wed", + "thu", + "fri", + "sat" + ] + }, + "mode": { + "type": "string", + "enum": [ + "specific_hours", + "open_24h", + "appointment_only" + ] + }, + "openTime": { + "type": "integer", + "minimum": 0, + "maximum": 1439 + }, + "closeTime": { + "type": "integer", + "minimum": 0, + "maximum": 1439 + } + }, + "required": [ + "dayOfWeek", + "mode" + ] + }, + "minItems": 1, + "maxItems": 7 + } + }, + "required": [ + "timeZone", + "days" + ] + } + } + }, + "SetBusinessCoverPhotoResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "coverPhotoId": { + "type": "string" + } + }, + "required": [ + "coverPhotoId" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessCoverPhotoRequest": { + "type": "object", + "properties": { + "url": { + "type": "string", + "maxLength": 2048, + "format": "uri" + }, + "base64": { + "type": "string", + "minLength": 1, + "maxLength": 6990508 + } + } + }, + "DeleteBusinessCoverPhotoResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "status": { + "type": "string" + } + }, + "required": [ + "status" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessMerchantCompliance": { + "type": "object", + "properties": { + "entityName": { + "type": "string", + "maxLength": 256 + }, + "entityType": { + "type": "string", + "enum": [ + "SOLE_PROPRIETORSHIP", + "PARTNERSHIP", + "PRIVATE_COMPANY", + "PUBLIC_COMPANY", + "LIMITED_LIABILITY_PARTNERSHIP", + "OTHER" + ] + }, + "isRegistered": { + "type": "boolean" + }, + "entityTypeCustom": { + "type": "string", + "maxLength": 256 + }, + "customerCare": { + "type": "object", + "properties": { + "email": { + "type": "string", + "maxLength": 254 + }, + "landlineNumber": { + "type": "string", + "maxLength": 64 + }, + "mobileNumber": { + "type": "string", + "maxLength": 64 + } + }, + "required": [ + "email", + "landlineNumber", + "mobileNumber" + ], + "additionalProperties": false + }, + "grievanceOfficer": { + "type": "object", + "properties": { + "email": { + "type": "string", + "maxLength": 254 + }, + "landlineNumber": { + "type": "string", + "maxLength": 64 + }, + "mobileNumber": { + "type": "string", + "maxLength": 64 + }, + "name": { + "type": "string", + "maxLength": 256 + } + }, + "required": [ + "email", + "landlineNumber", + "mobileNumber", + "name" + ], + "additionalProperties": false + } + }, + "required": [ + "entityName", + "entityType", + "isRegistered", + "entityTypeCustom", + "customerCare", + "grievanceOfficer" + ], + "additionalProperties": false + }, + "GetBusinessMerchantComplianceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessMerchantCompliance" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetBusinessMerchantComplianceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessMerchantCompliance" + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessQuickReplyMutation": { + "type": "object", + "properties": { + "shortcut": { + "type": "string", + "minLength": 1, + "maxLength": 25, + "pattern": "^[\\p{L}\\p{N}]+$" + }, + "message": { + "type": "string", + "minLength": 1, + "maxLength": 65536 + }, + "keywords": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "maxItems": 100, + "default": [] + }, + "count": { + "type": "integer", + "minimum": 0, + "maximum": 2147483647, + "default": 0 + } + }, + "required": [ + "shortcut", + "message" + ] + }, + "BusinessQuickReply": { + "allOf": [ + { + "$ref": "#/components/schemas/BusinessQuickReplyMutation" + }, + { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + } + ] + }, + "CreateBusinessQuickReplyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessQuickReply" + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessQuickReplyObserved": { + "allOf": [ + { + "$ref": "#/components/schemas/BusinessQuickReply" + }, + { + "type": "object", + "properties": { + "associatedLabelIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "observedAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "associatedLabelIds", + "observedAt" + ] + } + ] + }, + "BusinessQuickReplyCollection": { + "type": "object", + "properties": { + "policy": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "status": { + "type": "string", + "enum": [ + "disabled", + "unknown", + "partial", + "fresh" + ] + }, + "unknownReason": { + "type": "string", + "enum": [ + "observation_disabled", + "not_retained", + "not_observed" + ] + }, + "observedAt": { + "type": "string", + "format": "date-time" + }, + "quickReplies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BusinessQuickReplyObserved" + } + } + }, + "required": [ + "policy", + "status", + "quickReplies" + ] + }, + "ListBusinessQuickRepliesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessQuickReplyCollection" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetBusinessQuickReplyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessQuickReply" + } + }, + "required": [ + "success", + "data" + ] + }, + "DeleteBusinessQuickReplyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "DELETED" + ] + } + }, + "required": [ + "id", + "status" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessProduct": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "retailerId": { + "type": "string" + }, + "belongsTo": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "price": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + }, + "shimmedUrl": { + "type": "string", + "format": "uri" + }, + "hidden": { + "type": "boolean" + }, + "sanctioned": { + "type": "boolean" + }, + "maxAvailable": { + "type": "integer", + "minimum": 0 + }, + "availability": { + "type": "string" + }, + "complianceCategory": { + "type": "string" + }, + "compliance": { + "type": "object", + "properties": { + "countryCodeOrigin": { + "type": "string" + }, + "importerName": { + "type": "string" + }, + "importerAddress": { + "type": "object", + "properties": { + "street1": { + "type": "string" + }, + "street2": { + "type": "string" + }, + "city": { + "type": "string" + }, + "region": { + "type": "string" + }, + "postalCode": { + "type": "string" + }, + "countryCode": { + "type": "string" + } + } + } + } + }, + "media": { + "type": "object", + "properties": { + "images": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "originalUrl": { + "type": "string", + "format": "uri" + }, + "requestUrl": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "id" + ] + } + }, + "videos": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "originalUrl": { + "type": "string", + "format": "uri" + }, + "thumbnailUrl": { + "type": "string", + "format": "uri" + } + }, + "required": [ + "id" + ] + } + } + }, + "required": [ + "images", + "videos" + ] + }, + "salePrice": { + "type": "object", + "properties": { + "price": { + "type": "string" + }, + "startDate": { + "type": "string" + }, + "endDate": { + "type": "string" + } + }, + "required": [ + "price" + ] + }, + "status": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "canAppeal": { + "type": "boolean" + } + }, + "required": [ + "canAppeal" + ] + }, + "variant": { + "type": "object", + "properties": { + "availability": { + "type": "object", + "properties": { + "listings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "productId": { + "type": "string" + }, + "available": { + "type": "boolean" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ] + } + } + }, + "required": [ + "available", + "options" + ] + } + } + }, + "required": [ + "listings" + ] + }, + "listingDetails": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "lowestPrice": { + "type": "string" + }, + "multiPrice": { + "type": "string" + } + } + }, + "types": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "thumbnail": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "originalUrl": { + "type": "string", + "format": "uri" + }, + "requestUrl": { + "type": "string", + "format": "uri" + }, + "originalDimensions": { + "type": "object", + "properties": { + "width": { + "type": "integer", + "minimum": 0 + }, + "height": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "required": [ + "originalDimensions" + ] + } + }, + "required": [ + "value" + ] + } + } + }, + "required": [ + "name", + "options" + ] + } + }, + "properties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ] + } + } + }, + "required": [ + "availability", + "listingDetails", + "types", + "properties" + ] + } + }, + "required": [ + "id", + "name", + "price", + "currency", + "hidden", + "sanctioned", + "media", + "status" + ] + }, + "BusinessCatalogPage": { + "type": "object", + "properties": { + "next": { + "type": "string" + }, + "previous": { + "type": "string" + }, + "products": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BusinessProduct" + } + } + }, + "required": [ + "products" + ] + }, + "GetBusinessCatalogResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessCatalogPage" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateBusinessCatalogResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "SetBusinessCartEnabledResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessCartSettingRequest": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false + }, + "GetBusinessProductResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessProduct" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateBusinessProductResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessProduct" + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessProductMutationRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "description": { + "type": "string", + "maxLength": 4096 + }, + "currency": { + "type": "string", + "pattern": "^[A-Z]{3}$" + }, + "price": { + "type": "string", + "pattern": "^\\d{1,18}$" + }, + "salePrice": { + "type": "string", + "pattern": "^\\d{1,18}$" + }, + "url": { + "type": "string", + "maxLength": 2048, + "format": "uri" + }, + "retailerId": { + "type": "string", + "maxLength": 256 + }, + "hidden": { + "type": "boolean" + }, + "images": { + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string", + "maxLength": 4096, + "format": "uri", + "description": "HTTPS image source fetched through Polymorfa's SSRF-safe downloader" + }, + "base64": { + "type": "string", + "minLength": 1, + "maxLength": 22369624 + }, + "mediaUrl": { + "type": "string", + "maxLength": 4096, + "format": "uri", + "description": "Already-uploaded WhatsApp or Meta media URL reused without downloading" + } + }, + "additionalProperties": false + }, + "minItems": 1, + "maxItems": 10 + }, + "videoUrls": { + "type": "array", + "items": { + "type": "string", + "maxLength": 4096, + "format": "uri" + }, + "maxItems": 10 + }, + "complianceCategory": { + "type": "string", + "maxLength": 128 + }, + "compliance": { + "type": "object", + "properties": { + "countryCodeOrigin": { + "type": "string", + "maxLength": 3 + }, + "importerName": { + "type": "string", + "maxLength": 256 + }, + "importerAddress": { + "type": "object", + "properties": { + "street1": { + "type": "string", + "maxLength": 512 + }, + "street2": { + "type": "string", + "maxLength": 512 + }, + "city": { + "type": "string", + "maxLength": 256 + }, + "region": { + "type": "string", + "maxLength": 256 + }, + "postalCode": { + "type": "string", + "maxLength": 64 + }, + "countryCode": { + "type": "string", + "maxLength": 3 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "width": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "height": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + } + }, + "required": [ + "name", + "images" + ], + "additionalProperties": false + }, + "UpdateBusinessProductResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessProduct" + } + }, + "required": [ + "success", + "data" + ] + }, + "DeleteBusinessProductResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "deletedCount": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "deletedCount" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "SetBusinessProductVisibilityResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessProductVisibilityRequest": { + "type": "object", + "properties": { + "hidden": { + "type": "boolean" + } + }, + "required": [ + "hidden" + ], + "additionalProperties": false + }, + "AppealBusinessProductResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessCatalogAppealRequest": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "minLength": 1, + "maxLength": 4096 + } + }, + "required": [ + "reason" + ], + "additionalProperties": false + }, + "BusinessCollection": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "products": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BusinessProduct" + } + }, + "status": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "canAppeal": { + "type": "boolean" + }, + "commerceUrl": { + "type": "string", + "format": "uri" + }, + "rejectReason": { + "type": "string" + } + }, + "required": [ + "canAppeal" + ] + } + }, + "required": [ + "id", + "name", + "products", + "status" + ] + }, + "BusinessCollectionPage": { + "type": "object", + "properties": { + "next": { + "type": "string" + }, + "collections": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BusinessCollection" + } + } + }, + "required": [ + "collections" + ] + }, + "GetBusinessCollectionsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessCollectionPage" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateBusinessCollectionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "reviewStatus": { + "type": "string" + } + }, + "required": [ + "id", + "reviewStatus" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessCollectionCreateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "productIds": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "minItems": 1, + "maxItems": 100 + } + }, + "required": [ + "name", + "productIds" + ], + "additionalProperties": false + }, + "GetBusinessCollectionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessCollection" + } + }, + "required": [ + "success", + "data" + ] + }, + "ReorderBusinessCollectionsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessCollectionReorderRequest": { + "type": "object", + "properties": { + "moves": { + "type": "array", + "items": { + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "fromIndex": { + "type": "integer", + "minimum": 0, + "maximum": 99 + }, + "toIndex": { + "type": "integer", + "minimum": 0, + "maximum": 99 + } + }, + "required": [ + "collectionId", + "fromIndex", + "toIndex" + ], + "additionalProperties": false + }, + "minItems": 1, + "maxItems": 100 + } + }, + "required": [ + "moves" + ], + "additionalProperties": false + }, + "UpdateBusinessCollectionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "reviewStatus": { + "type": "string" + } + }, + "required": [ + "id", + "reviewStatus" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessCollectionUpdateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "addProductIds": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "minItems": 0, + "maxItems": 100 + }, + "removeProductIds": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "minItems": 0, + "maxItems": 100 + } + }, + "additionalProperties": false + }, + "DeleteBusinessCollectionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "AppealBusinessCollectionResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "success" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessOrder": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "createdAt": { + "type": "integer", + "minimum": 0 + }, + "catalogId": { + "type": "string" + }, + "price": { + "type": "object", + "properties": { + "subtotal": { + "type": "string" + }, + "total": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "priceStatus": { + "type": "string" + } + }, + "required": [ + "subtotal", + "total", + "currency" + ] + }, + "products": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "imageId": { + "type": "string" + }, + "imageUrl": { + "type": "string", + "format": "uri" + }, + "price": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "name": { + "type": "string" + }, + "quantity": { + "type": "integer", + "minimum": 0 + }, + "variantProperties": { + "type": "string" + } + }, + "required": [ + "id", + "price", + "currency", + "name", + "quantity" + ] + } + } + }, + "required": [ + "id", + "createdAt", + "price", + "products" + ] + }, + "GetBusinessOrderResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/BusinessOrder" + } + }, + "required": [ + "success", + "data" + ] + }, + "BusinessOrderLookupRequest": { + "type": "object", + "properties": { + "token": { + "type": "string", + "minLength": 1, + "maxLength": 8192 + } + }, + "required": [ + "token" + ] + }, + "ResolveIdentityResult": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "keyRequired": { + "type": "boolean" + } + } + }, + "ResolveIdentityResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ResolveIdentityResult" + } + }, + "required": [ + "success", + "data" + ] + }, + "UserSecurityCode": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "phoneNumber": { + "type": "string" + }, + "username": { + "type": "string" + }, + "numericCode": { + "type": "string", + "pattern": "^\\d{60}$" + }, + "qrCode": { + "type": "string" + } + }, + "required": [ + "id", + "numericCode", + "qrCode" + ] + }, + "UserSecurityCodeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/UserSecurityCode" + } + }, + "required": [ + "success", + "data" + ] + }, + "Channel": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "profileUrl": { + "type": "string" + }, + "followers": { + "type": "number" + }, + "muted": { + "type": "boolean" + }, + "preview": { + "type": "boolean" + } + } + }, + "ListChannelsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Channel" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateChannelResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Channel" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateChannelRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string" + }, + "picture": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "GetChannelResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Channel" + } + }, + "required": [ + "success", + "data" + ] + }, + "ChannelMessage": { + "type": "object", + "properties": { + "serverId": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "views": { + "type": "integer", + "minimum": 0 + }, + "reactionCounts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 0 + } + }, + "text": { + "type": "string" + } + }, + "required": [ + "serverId", + "id", + "type", + "timestamp", + "views", + "reactionCounts" + ] + }, + "ListChannelMessagesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelMessage" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "ListChannelMessageUpdatesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelMessage" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "ChannelReactionRequest": { + "type": "object", + "properties": { + "reaction": { + "type": "string", + "maxLength": 32 + } + }, + "required": [ + "reaction" + ] + }, + "ChannelLiveUpdates": { + "type": "object", + "properties": { + "durationSeconds": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + } + }, + "required": [ + "durationSeconds" + ] + }, + "ChannelLiveUpdatesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ChannelLiveUpdates" + } + }, + "required": [ + "success", + "data" + ] + }, + "DeleteChannelResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "DELETED" + ] + } + }, + "required": [ + "status" + ] + } + }, + "required": [ + "success", + "data" + ] + }, + "SetPresenceRequest": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "available", + "unavailable" + ] + } + }, + "required": [ + "presence" + ] + }, + "PresenceData": { + "type": "object", + "properties": { + "desired": { + "type": "string", + "enum": [ + "available", + "unavailable" + ] + }, + "desiredAt": { + "type": "string", + "format": "date-time" + }, + "lastSent": { + "type": "string", + "enum": [ + "available", + "unavailable" + ] + }, + "lastSentAt": { + "type": "string", + "format": "date-time" + }, + "authoritative": { + "type": "boolean", + "enum": [ + false + ] + } + }, + "required": [ + "authoritative" + ] + }, + "GetPresenceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/PresenceData" + } + }, + "required": [ + "success", + "data" + ] + }, + "ChatPresenceData": { + "type": "object", + "properties": { + "policy": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "status": { + "type": "string", + "enum": [ + "unknown", + "fresh", + "stale" + ] + }, + "unknownReason": { + "type": "string", + "enum": [ + "disabled", + "not_observed", + "suspended" + ] + }, + "available": { + "type": "boolean" + }, + "lastSeen": { + "type": "string", + "format": "date-time" + }, + "observedAt": { + "type": "string", + "format": "date-time" + }, + "subscriptionExpiresAt": { + "type": "string", + "format": "date-time" + }, + "stale": { + "type": "boolean" + }, + "typingPolicy": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "typingStatus": { + "type": "string", + "enum": [ + "unknown", + "fresh", + "stale" + ] + }, + "typingUnknownReason": { + "type": "string", + "enum": [ + "disabled", + "not_observed", + "suspended" + ] + }, + "chatState": { + "type": "object", + "properties": { + "sender": { + "type": "string" + }, + "state": { + "type": "string", + "enum": [ + "composing", + "paused" + ] + }, + "media": { + "type": "string" + }, + "observedAt": { + "type": "string", + "format": "date-time" + }, + "stale": { + "type": "boolean" + } + }, + "required": [ + "sender", + "state", + "observedAt", + "stale" + ] + } + }, + "required": [ + "policy", + "status", + "stale", + "typingPolicy", + "typingStatus" + ] + }, + "GetChatPresenceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ChatPresenceData" + } + }, + "required": [ + "success", + "data" + ] + }, + "PresenceSubscriptionData": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "SUBSCRIBED" + ] + }, + "expiresAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "status", + "expiresAt" + ] + }, + "SubscribePresenceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/PresenceSubscriptionData" + } + }, + "required": [ + "success", + "data" + ] + }, + "ProjectSafeMode": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "ceiling": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "off", + "jittered", + "conversation" + ] + }, + "onlineStart": { + "type": "integer", + "minimum": 0, + "maximum": 23 + }, + "onlineEnd": { + "type": "integer", + "minimum": 0, + "maximum": 23 + } + }, + "required": [ + "presence", + "typing", + "reads", + "pacing", + "onlineStart", + "onlineEnd" + ] + }, + "entitled": { + "type": "boolean" + }, + "entitlementReason": { + "type": "string", + "nullable": true + } + }, + "required": [ + "projectId", + "ceiling", + "entitled", + "entitlementReason" + ] + }, + "GetProjectSafeModeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectSafeMode" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateProjectSafeModeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectSafeMode" + } + }, + "required": [ + "success", + "data" + ] + }, + "SessionSafeMode": { + "type": "object", + "properties": { + "session": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "project": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "off", + "jittered", + "conversation" + ] + }, + "onlineStart": { + "type": "integer", + "minimum": 0, + "maximum": 23 + }, + "onlineEnd": { + "type": "integer", + "minimum": 0, + "maximum": 23 + } + }, + "required": [ + "presence", + "typing", + "reads", + "pacing", + "onlineStart", + "onlineEnd" + ] + }, + "override": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "inherit", + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "inherit", + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "inherit", + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "inherit", + "off", + "jittered", + "conversation" + ] + } + }, + "required": [ + "presence", + "typing", + "reads", + "pacing" + ] + }, + "effective": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "off", + "jittered", + "conversation" + ] + }, + "onlineStart": { + "type": "integer", + "minimum": 0, + "maximum": 23 + }, + "onlineEnd": { + "type": "integer", + "minimum": 0, + "maximum": 23 + } + }, + "required": [ + "presence", + "typing", + "reads", + "pacing", + "onlineStart", + "onlineEnd" + ] + }, + "applied": { + "type": "object", + "nullable": true, + "properties": { + "observedAt": { + "type": "string" + }, + "presence": { + "type": "string", + "nullable": true + }, + "typing": { + "type": "string", + "nullable": true + }, + "reads": { + "type": "string", + "nullable": true + }, + "pacing": { + "type": "string", + "nullable": true + } + }, + "required": [ + "observedAt", + "presence", + "typing", + "reads", + "pacing" + ] + }, + "mismatch": { + "type": "boolean" + }, + "entitled": { + "type": "boolean" + }, + "entitlementReason": { + "type": "string", + "nullable": true + } + }, + "required": [ + "session", + "projectId", + "project", + "override", + "effective", + "applied", + "mismatch", + "entitled", + "entitlementReason" + ] + }, + "GetSessionSafeModeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SessionSafeMode" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateSessionSafeModeResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SessionSafeMode" + } + }, + "required": [ + "success", + "data" + ] + }, + "ProjectWarmupPlan": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "plan": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "warmupDays": { + "type": "integer", + "minimum": 1, + "maximum": 90 + }, + "dailyStart": { + "type": "integer", + "minimum": 1, + "maximum": 2000 + } + }, + "required": [ + "enabled", + "warmupDays", + "dailyStart" + ] + }, + "ceiling": { + "type": "integer", + "minimum": 1 + }, + "curve": { + "type": "array", + "items": { + "type": "object", + "properties": { + "day": { + "type": "integer", + "minimum": 0 + }, + "allowance": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "day", + "allowance" + ] + }, + "maxItems": 91 + }, + "entitled": { + "type": "boolean" + }, + "entitlementReason": { + "type": "string", + "nullable": true + } + }, + "required": [ + "projectId", + "plan", + "ceiling", + "curve", + "entitled", + "entitlementReason" + ] + }, + "GetProjectWarmupPlanResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectWarmupPlan" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateProjectWarmupPlanResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectWarmupPlan" + } + }, + "required": [ + "success", + "data" + ] + }, + "ProjectHealthPolicy": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "version": { + "type": "integer", + "minimum": 0 + }, + "enabled": { + "type": "boolean" + }, + "threshold": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "sessionAction": { + "type": "string", + "enum": [ + "none", + "stop", + "slow_down", + "log_out" + ] + }, + "slowDownMps": { + "type": "number", + "nullable": true, + "minimum": 0, + "exclusiveMinimum": true + }, + "emailNotification": { + "type": "boolean" + }, + "webhookNotification": { + "type": "boolean" + }, + "integrations": { + "type": "object", + "properties": { + "emailConfigured": { + "type": "boolean" + }, + "webhookConfigured": { + "type": "boolean" + } + }, + "required": [ + "emailConfigured", + "webhookConfigured" + ] + } + }, + "required": [ + "projectId", + "version", + "enabled", + "threshold", + "sessionAction", + "slowDownMps", + "emailNotification", + "webhookNotification", + "integrations" + ] + }, + "GetProjectHealthPolicyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectHealthPolicy" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateProjectHealthPolicyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectHealthPolicy" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateProjectHealthPolicyInput": { + "type": "object", + "properties": { + "version": { + "type": "integer", + "minimum": 0 + }, + "enabled": { + "type": "boolean" + }, + "threshold": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "sessionAction": { + "type": "string", + "enum": [ + "none", + "stop", + "slow_down", + "log_out" + ] + }, + "slowDownMps": { + "type": "number", + "nullable": true, + "minimum": 0, + "exclusiveMinimum": true + }, + "emailNotification": { + "type": "boolean" + }, + "webhookNotification": { + "type": "boolean" + } + }, + "required": [ + "version", + "enabled", + "threshold", + "sessionAction", + "slowDownMps", + "emailNotification", + "webhookNotification" + ], + "additionalProperties": false + }, + "ProjectInsuranceEvidence": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "enabled": { + "type": "boolean" + }, + "banInsuranceIncluded": { + "type": "boolean" + } + }, + "required": [ + "projectId", + "enabled", + "banInsuranceIncluded" + ] + }, + "GetProjectInsuranceEvidenceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectInsuranceEvidence" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateProjectInsuranceEvidenceResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectInsuranceEvidence" + } + }, + "required": [ + "success", + "data" + ] + }, + "ProjectObservationPolicy": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "presenceMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "typingMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "labelMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache", + "project" + ] + }, + "quickReplyMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + } + }, + "required": [ + "projectId", + "presenceMode", + "typingMode", + "labelMode", + "quickReplyMode" + ] + }, + "GetProjectObservationPolicyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectObservationPolicy" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateProjectObservationPolicyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProjectObservationPolicy" + } + }, + "required": [ + "success", + "data" + ] + }, + "SessionObservationPolicy": { + "type": "object", + "properties": { + "sessionName": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "project": { + "type": "object", + "properties": { + "presenceMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "typingMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "labelMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache", + "project" + ] + }, + "quickReplyMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + } + }, + "required": [ + "presenceMode", + "typingMode", + "labelMode", + "quickReplyMode" + ] + }, + "override": { + "type": "object", + "properties": { + "presenceMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache" + ] + }, + "typingMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache" + ] + }, + "labelMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache", + "project" + ] + }, + "quickReplyMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache" + ] + } + }, + "required": [ + "presenceMode", + "typingMode", + "labelMode", + "quickReplyMode" + ] + }, + "effective": { + "type": "object", + "properties": { + "presenceMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "typingMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "labelMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache", + "project" + ] + }, + "quickReplyMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + } + }, + "required": [ + "presenceMode", + "typingMode", + "labelMode", + "quickReplyMode" + ] + } + }, + "required": [ + "sessionName", + "projectId", + "project", + "override", + "effective" + ] + }, + "GetSessionObservationPolicyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SessionObservationPolicy" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateSessionObservationPolicyResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/SessionObservationPolicy" + } + }, + "required": [ + "success", + "data" + ] + }, + "ProfileData": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "profilePicUrl": { + "type": "string" + } + }, + "required": [ + "name", + "status" + ] + }, + "GetProfileResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/ProfileData" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetProfileNameRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name" + ] + }, + "SetProfileStatusRequest": { + "type": "object", + "properties": { + "status": { + "type": "string" + } + }, + "required": [ + "status" + ] + }, + "SetProfilePictureRequest": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "base64": { + "type": "string" + } + } + }, + "PrivacySettings": { + "type": "object", + "properties": { + "groupAdd": { + "type": "string" + }, + "lastSeen": { + "type": "string" + }, + "status": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "readReceipts": { + "type": "string" + }, + "online": { + "type": "string" + }, + "callAdd": { + "type": "string" + }, + "messages": { + "type": "string" + }, + "defense": { + "type": "string" + }, + "stickers": { + "type": "string" + } + }, + "required": [ + "groupAdd", + "lastSeen", + "status", + "profile", + "readReceipts", + "online", + "callAdd", + "messages", + "defense", + "stickers" + ] + }, + "PrivacySettingsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/PrivacySettings" + } + }, + "required": [ + "success", + "data" + ] + }, + "DefaultDisappearingTimerRequest": { + "type": "object", + "properties": { + "durationSeconds": { + "anyOf": [ + { + "type": "number", + "enum": [ + 0 + ] + }, + { + "type": "number", + "enum": [ + 86400 + ] + }, + { + "type": "number", + "enum": [ + 604800 + ] + }, + { + "type": "number", + "enum": [ + 7776000 + ] + } + ] + } + }, + "required": [ + "durationSeconds" + ] + }, + "UpdatedPrivacySettingsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/PrivacySettings" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetPrivacySettingRequest": { + "type": "object", + "properties": { + "value": { + "type": "string", + "enum": [ + "all", + "contacts", + "contact_allowlist", + "contact_blacklist", + "match_last_seen", + "known", + "none", + "on_standard", + "off" + ] + } + }, + "required": [ + "value" + ] + }, + "Label": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "color": { + "type": "integer" + }, + "orderIndex": { + "type": "integer" + }, + "chatCount": { + "type": "integer" + }, + "observedAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "name", + "color" + ] + }, + "LabelCollection": { + "type": "object", + "properties": { + "policy": { + "type": "string", + "enum": [ + "off", + "events", + "cache", + "project" + ] + }, + "status": { + "type": "string", + "enum": [ + "disabled", + "unknown", + "partial", + "fresh" + ] + }, + "unknownReason": { + "type": "string", + "enum": [ + "observation_disabled", + "not_retained", + "not_observed", + "expired" + ] + }, + "observedAt": { + "type": "string", + "format": "date-time" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "labels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + } + }, + "required": [ + "policy", + "status", + "labels" + ] + }, + "LabelReadData": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/Label" + } + }, + { + "$ref": "#/components/schemas/LabelCollection" + } + ] + }, + "ListLabelsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/LabelReadData" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateLabelResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Label" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateLabelRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 100 + }, + "color": { + "type": "integer", + "minimum": 0, + "maximum": 19 + } + }, + "required": [ + "name" + ] + }, + "UpdateLabelRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 100 + }, + "color": { + "type": "integer", + "minimum": 0, + "maximum": 19 + } + } + }, + "GetChatLabelsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/LabelReadData" + } + }, + "required": [ + "success", + "data" + ] + }, + "SetChatLabelsRequest": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "maxItems": 20 + } + }, + "required": [ + "labels" + ] + }, + "RetryConfig": { + "type": "object", + "properties": { + "attempts": { + "type": "integer", + "minimum": 0 + }, + "delaySeconds": { + "type": "integer", + "minimum": 0 + }, + "policy": { + "type": "string", + "description": "linear, exponential, or constant" + } + }, + "required": [ + "attempts", + "delaySeconds", + "policy" + ] + }, + "WebhookHeader": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ] + }, + "Webhook": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "tenantId": { + "type": "string" + }, + "session": { + "type": "string" + }, + "url": { + "type": "string" + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "retries": { + "$ref": "#/components/schemas/RetryConfig" + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebhookHeader" + } + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + }, + "createdAt": { + "type": "string" + } + }, + "required": [ + "id", + "tenantId", + "url", + "events", + "retries", + "headers", + "enabled", + "createdAt" + ] + }, + "ListWebhooksResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Webhook" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateWebhookResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Webhook" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateWebhookRequest": { + "type": "object", + "properties": { + "session": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "hmacKey": { + "type": "string" + }, + "retries": { + "$ref": "#/components/schemas/RetryConfig" + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebhookHeader" + } + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ], + "description": "\"native\" (default) = Polymorfa event envelope. \"meta\" = Meta Cloud API webhook shape (object/entry/changes/value), signed with X-Hub-Signature-256." + } + }, + "required": [ + "url" + ] + }, + "GetWebhookResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Webhook" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateWebhookResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Webhook" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateWebhookRequest": { + "type": "object", + "properties": { + "url": { + "type": "string", + "format": "uri" + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "hmacKey": { + "type": "string" + }, + "retries": { + "$ref": "#/components/schemas/RetryConfig" + }, + "headers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebhookHeader" + } + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + } + } + }, + "MediaInfo": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "session": { + "type": "string" + }, + "messageId": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "fileLength": { + "type": "integer", + "minimum": 0 + }, + "persisted": { + "type": "boolean" + }, + "s3Url": { + "type": "string" + } + }, + "required": [ + "id", + "session", + "messageId", + "mimeType", + "fileLength", + "persisted" + ] + }, + "GetMediaInfoResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/MediaInfo" + } + }, + "required": [ + "success", + "data" + ] + }, + "MessageTemplate": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "category": { + "type": "string" + }, + "language": { + "type": "string" + }, + "status": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "definition": {}, + "sampleValues": {}, + "cloudLinks": { + "type": "array", + "items": {} + }, + "createdAt": { + "type": "number" + }, + "updatedAt": { + "type": "number" + } + }, + "required": [ + "id", + "name", + "category", + "language", + "status", + "kind", + "cloudLinks", + "createdAt", + "updatedAt" + ] + }, + "ListProjectTemplatesResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageTemplate" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "GetProjectTemplateResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/MessageTemplate" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateProjectTemplateResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/MessageTemplate" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateMessageTemplateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "pattern": "^[a-z0-9_]+$" + }, + "definition": { + "type": "object", + "additionalProperties": {} + }, + "sampleValues": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "name", + "definition" + ] + }, + "UpdateProjectTemplateResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/MessageTemplate" + } + }, + "required": [ + "success", + "data" + ] + }, + "UpdateMessageTemplateRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "status": { + "type": "string" + }, + "definition": { + "type": "object", + "additionalProperties": {} + }, + "sampleValues": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + }, + "PreviewProjectTemplateResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "additionalProperties": {} + } + }, + "required": [ + "success", + "data" + ] + }, + "PreviewMessageTemplateRequest": { + "type": "object", + "properties": { + "values": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "surface": { + "type": "string", + "enum": [ + "cloud", + "whatsmeow", + "sandbox" + ] + } + } + }, + "SubmitProjectTemplateResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "additionalProperties": {} + } + }, + "required": [ + "success", + "data" + ] + }, + "SubmitMessageTemplateRequest": { + "type": "object", + "properties": { + "session": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "session" + ] + }, + "Campaign": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "templateId": { + "type": "string", + "nullable": true + }, + "recipientListId": { + "type": "string", + "nullable": true + }, + "recipientCount": { + "type": "number" + }, + "sentCount": { + "type": "number" + }, + "deliveredCount": { + "type": "number" + }, + "readCount": { + "type": "number" + }, + "failedCount": { + "type": "number" + }, + "skippedCount": { + "type": "number" + }, + "scheduledAt": { + "type": "number", + "nullable": true + }, + "launchedAt": { + "type": "number", + "nullable": true + }, + "completedAt": { + "type": "number", + "nullable": true + }, + "createdAt": { + "type": "number" + }, + "updatedAt": { + "type": "number" + } + }, + "required": [ + "id", + "name", + "status", + "templateId", + "recipientListId", + "recipientCount", + "sentCount", + "deliveredCount", + "readCount", + "failedCount", + "skippedCount", + "scheduledAt", + "launchedAt", + "completedAt", + "createdAt", + "updatedAt" + ] + }, + "ListCampaignsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Campaign" + } + } + }, + "required": [ + "success", + "data" + ] + }, + "GetCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Campaign" + } + }, + "required": [ + "success", + "data" + ] + }, + "CampaignAnalyticsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "additionalProperties": {} + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/Campaign" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateCampaignRequest": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "templateId": { + "type": "string" + }, + "recipientListId": { + "type": "string" + }, + "senderConfig": { + "type": "object", + "additionalProperties": {} + }, + "scheduledAt": { + "type": "number" + } + }, + "required": [ + "name" + ] + }, + "CampaignOperation": { + "allOf": [ + { + "$ref": "#/components/schemas/Campaign" + }, + { + "type": "object", + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "operationId" + ] + } + ] + }, + "LaunchCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/CampaignOperation" + } + }, + "required": [ + "success", + "data" + ] + }, + "LaunchCampaignRequest": { + "type": "object", + "properties": { + "scheduledAt": { + "type": "number" + } + } + }, + "PauseCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/CampaignOperation" + } + }, + "required": [ + "success", + "data" + ] + }, + "ResumeCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/CampaignOperation" + } + }, + "required": [ + "success", + "data" + ] + }, + "StopCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/CampaignOperation" + } + }, + "required": [ + "success", + "data" + ] + }, + "RequeueCampaignResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "type": "object", + "additionalProperties": {} + } + }, + "required": [ + "success", + "data" + ] + }, + "RequeueCampaignRequest": { + "type": "object", + "properties": { + "includeSkippedError": { + "type": "boolean" + } + } + }, + "QuickLink": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Stable QuickLink identifier, prefixed `ql_`." + }, + "url": { + "type": "string", + "description": "Hosted connection URL. Share it only with the person holding the phone." + }, + "session": { + "type": "string", + "description": "Session name that receives the connected number." + }, + "expiresAt": { + "type": "string", + "description": "ISO-8601 expiry. QuickLinks live 15 minutes unless `expiresInSeconds` was set." + } + }, + "required": [ + "id", + "url", + "session", + "expiresAt" + ] + }, + "QuickLinkResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/QuickLink" + } + }, + "required": [ + "success", + "data" + ] + }, + "CreateQuickLinkRequest": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "format": "uuid", + "description": "Project that receives the connected number. Required for organization keys with more than one project." + }, + "customerId": { + "type": "string", + "format": "uuid", + "description": "Customer that owns the connected number when Customers is enabled for the project." + }, + "methods": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "qr", + "pairing" + ] + }, + "minItems": 1, + "maxItems": 2, + "description": "Connection methods offered on the hosted page. Defaults to the saved settings, then to both." + }, + "businessName": { + "type": "string", + "minLength": 1, + "maxLength": 120, + "description": "Name shown to the recipient when no saved business name exists." + }, + "historySync": { + "type": "string", + "enum": [ + "ask", + "force_on", + "force_off" + ] + }, + "callbackUrl": { + "type": "string", + "maxLength": 2048, + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]://", + "description": "Exact HTTPS URL without credentials. Must match a saved redirect URL." + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system" + ] + }, + "accent": { + "type": "string", + "pattern": "^#[0-9a-fA-F]{6}$" + }, + "prefillPhone": { + "type": "string", + "pattern": "^\\+?\\d{6,15}$", + "description": "Pre-fills the phone number for the pairing-code method." + }, + "expiresInSeconds": { + "type": "integer", + "minimum": 300, + "maximum": 3600, + "description": "Link lifetime in seconds, 300–3600. Defaults to 900." + } + } + }, + "QuickLinkStatus": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "opened", + "linked", + "connected", + "failed", + "cancelled" + ] + }, + "session": { + "type": "string" + }, + "expiresAt": { + "type": "string" + }, + "openedAt": { + "type": "string", + "nullable": true + }, + "connectedAt": { + "type": "string", + "nullable": true + }, + "phone": { + "type": "string", + "nullable": true, + "description": "Connected phone in E.164 once the link is connected." + }, + "errorCode": { + "type": "string", + "nullable": true + } + }, + "required": [ + "id", + "status", + "session", + "expiresAt", + "openedAt", + "connectedAt", + "phone", + "errorCode" + ] + }, + "QuickLinkStatusResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "data": { + "$ref": "#/components/schemas/QuickLinkStatus" + } + }, + "required": [ + "success", + "data" + ] + }, + "QuickLinkState": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "opened", + "linked", + "connected", + "failed", + "cancelled" + ] + }, + "expiresAt": { + "type": "string" + }, + "methods": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "qr", + "pairing" + ] + } + }, + "defaultMethod": { + "type": "string", + "nullable": true, + "enum": [ + "qr", + "pairing", + null + ] + }, + "businessName": { + "type": "string" + }, + "headline": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "successMessage": { + "type": "string", + "nullable": true + }, + "supportUrl": { + "type": "string", + "nullable": true + }, + "privacyUrl": { + "type": "string", + "nullable": true + }, + "termsUrl": { + "type": "string", + "nullable": true + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system" + ] + }, + "accent": { + "type": "string", + "nullable": true + }, + "shape": { + "type": "string", + "nullable": true, + "enum": [ + "square", + "rounded", + "pill", + null + ] + }, + "radiusPx": { + "type": "number", + "nullable": true + }, + "logoUrl": { + "type": "string", + "nullable": true + }, + "hideWatermark": { + "type": "boolean" + }, + "historySync": { + "type": "string", + "enum": [ + "ask", + "force_on", + "force_off" + ] + }, + "prefillPhone": { + "type": "string", + "nullable": true + }, + "customer": { + "type": "boolean", + "description": "True when the link assigns the number to a Customer." + }, + "session": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "phone": { + "type": "string", + "nullable": true + } + }, + "required": [ + "status", + "phone" + ] + }, + "qrSvg": { + "type": "string", + "nullable": true, + "description": "Inline SVG of the current WhatsApp QR code, when the QR method is offered and the number is not linked yet." + }, + "errorCode": { + "type": "string", + "nullable": true + } + }, + "required": [ + "id", + "status", + "expiresAt", + "methods", + "defaultMethod", + "businessName", + "headline", + "description", + "successMessage", + "supportUrl", + "privacyUrl", + "termsUrl", + "theme", + "accent", + "shape", + "radiusPx", + "logoUrl", + "hideWatermark", + "historySync", + "prefillPhone", + "customer", + "session", + "qrSvg", + "errorCode" + ] + }, + "QuickLinkCodeRequest": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "minLength": 6, + "maxLength": 20 + } + }, + "required": [ + "phone" + ] + }, + "QuickLinkConfirmRequest": { + "type": "object", + "properties": { + "historySync": { + "type": "boolean" + } + } + } + }, + "securitySchemes": { + "BearerAuth": { + "type": "http", + "scheme": "bearer", + "description": "Polymorfa organization key (pmfa_ prefix), project token (pmfa_pt_ prefix) where supported, or short-lived client token (pmfa_ct_ prefix). Organization and project keys may be personal or service-account owned and enforce selected action scopes. Organization keys cover the team and its projects; project tokens stay inside one project. Client tokens stay inside their live project and session and enforce their client rules." + } + } + }, + "paths": { + "/ping": { + "get": { + "operationId": "ping", + "tags": [ + "Health" + ], + "summary": "Liveness probe", + "security": [], + "responses": { + "200": { + "description": "Pong", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PingResponse" + } + } + } + } + } + } + }, + "/health": { + "get": { + "operationId": "getHealth", + "tags": [ + "Health" + ], + "summary": "Full service health check", + "security": [], + "responses": { + "200": { + "description": "Required readiness checks pass; optional diagnostics may report degraded or in-progress state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthResponse" + } + } + } + }, + "503": { + "description": "One or more services unhealthy or draining", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthResponse" + } + } + } + } + } + } + }, + "/messaging/info/version": { + "get": { + "operationId": "getVersion", + "tags": [ + "Info" + ], + "summary": "Get API version info", + "security": [], + "responses": { + "200": { + "description": "Version info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionResponse" + } + } + } + } + } + } + }, + "/messaging/info/status": { + "get": { + "operationId": "getStatus", + "tags": [ + "Info" + ], + "summary": "Get API runtime status", + "security": [], + "responses": { + "200": { + "description": "Status info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StatusResponse" + } + } + } + } + } + } + }, + "/messaging/bridge/route": { + "get": { + "operationId": "getBridgeRoute", + "x-required-scope": "bridge:connect", + "tags": [ + "Bridge" + ], + "summary": "Verify a project token, resolve live project authority, and return the regional WSS endpoint.", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "wsUrl": { + "type": "string", + "format": "uri" + }, + "region": { + "type": "string", + "enum": [ + "BR", + "US", + "IN", + "Auto" + ] + }, + "kind": { + "type": "string", + "enum": [ + "sandbox", + "production" + ] + }, + "signal": { + "type": "string", + "enum": [ + "customer", + "bartender" + ] + }, + "tokenKind": { + "type": "string", + "enum": [ + "project" + ] + }, + "expiresAt": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "wsUrl", + "region", + "kind", + "signal", + "tokenKind", + "expiresAt" + ] + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "bridge:connect" + }, + "description": "**Required scope:** `bridge:connect`" + } + }, + "/messaging/client-tokens": { + "post": { + "operationId": "mintClientToken", + "tags": [ + "Client Tokens" + ], + "summary": "Mint a short-lived browser-safe client token", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scopes": [ + "sessions:manage", + "messages:write", + "contacts:read", + "presence:read", + "presence:observe", + "mcp" + ], + "x-required-scope-mode": "all", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MintClientTokenRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Token minted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MintClientTokenResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage messages:write contacts:read presence:read presence:observe mcp" + }, + "description": "**Required scopes (all):** `sessions:manage` · `messages:write` · `contacts:read` · `presence:read` · `presence:observe` · `mcp`" + } + }, + "/messaging/sessions/{session}/client-rules": { + "get": { + "operationId": "getClientRules", + "tags": [ + "Client Tokens" + ], + "summary": "Get client-token rules for a session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Client rules", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetClientRulesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + }, + "put": { + "operationId": "setClientRules", + "tags": [ + "Client Tokens" + ], + "summary": "Set client-token rules for a session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scopes": [ + "sessions:manage", + "messages:write", + "contacts:read", + "presence:read", + "presence:observe", + "mcp" + ], + "x-required-scope-mode": "all", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetClientRulesRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Rules saved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage messages:write contacts:read presence:read presence:observe mcp" + }, + "description": "**Required scopes (all):** `sessions:manage` · `messages:write` · `contacts:read` · `presence:read` · `presence:observe` · `mcp`" + }, + "delete": { + "operationId": "deleteClientRules", + "tags": [ + "Client Tokens" + ], + "summary": "Delete client-token rules for a session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Rules deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions": { + "get": { + "operationId": "listSessions", + "tags": [ + "Sessions" + ], + "summary": "List all sessions for the tenant", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "responses": { + "200": { + "description": "Session list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListSessionsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + }, + "description": "**Required scope:** `sessions:read`" + } + }, + "/messaging/sessions/{projectId}/": { + "post": { + "operationId": "createSession", + "tags": [ + "Sessions" + ], + "summary": "Create a new session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "description": "Project that owns the session." + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSessionRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Session created; a testing session is connected and command-ready before this response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSessionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Session with this name already exists", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}": { + "get": { + "operationId": "getSession", + "tags": [ + "Sessions" + ], + "summary": "Get session details", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Session details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetSessionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + }, + "description": "**Required scope:** `sessions:read`" + }, + "put": { + "operationId": "updateSession", + "tags": [ + "Sessions" + ], + "summary": "Update session configuration", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSessionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Session updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSessionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Session configuration was stored but the connected runner did not acknowledge it", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + }, + "delete": { + "operationId": "deleteSession", + "tags": [ + "Sessions" + ], + "summary": "Delete a session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Testing session deleted immediately after its simulated runtime closes", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationAccepted" + } + } + } + }, + "202": { + "description": "Session deletion scheduled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationAccepted" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/start": { + "post": { + "operationId": "startSession", + "tags": [ + "Sessions" + ], + "summary": "Start a session (connect to WhatsApp)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "202": { + "description": "Testing-session state changed immediately, or production-session start scheduled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationAccepted" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/stop": { + "post": { + "operationId": "stopSession", + "tags": [ + "Sessions" + ], + "summary": "Stop a session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "202": { + "description": "Testing session stopped after backend teardown, or production-session stop scheduled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationAccepted" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/restart": { + "post": { + "operationId": "restartSession", + "tags": [ + "Sessions" + ], + "summary": "Restart a session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "202": { + "description": "Testing session reconnected and ready, or production-session restart scheduled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationAccepted" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/logout": { + "post": { + "operationId": "logoutSession", + "tags": [ + "Sessions" + ], + "summary": "Log the session out of WhatsApp", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "202": { + "description": "Session logout scheduled", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationAccepted" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/me": { + "get": { + "operationId": "getSessionAccount", + "tags": [ + "Sessions" + ], + "summary": "Get the connected WhatsApp account info", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Account info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetSessionAccountResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + }, + "description": "**Required scope:** `sessions:read`" + } + }, + "/messaging/sessions/{session}/handoff-keys": { + "post": { + "operationId": "sessionHandoffKeys", + "tags": [ + "Sessions" + ], + "summary": "Initiate M↔P toggle: fetch the destination Curve25519 pubkey", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Destination pubkey + correlation id for the handoff", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HandoffKeysSuccess" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/handoff-import": { + "post": { + "operationId": "sessionHandoffImport", + "tags": [ + "Sessions" + ], + "summary": "Ship a sealed SignalStoreSnapshot from customer Baileys to the runner", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HandoffImportRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Import accepted; bartenderMode will flip after the runner acks", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HandoffImportSuccess" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/upload-appstate-keys": { + "post": { + "operationId": "sessionUploadAppStateKeys", + "tags": [ + "Sessions" + ], + "summary": "Upload selected AppStateSyncKeys (Track P+ tier)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadAppStateKeysRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Keys persisted; mode may have been flipped per upgradeTo", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UploadAppStateKeysSuccess" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/sessions/{session}/handoff-ack": { + "post": { + "operationId": "sessionHandoffAck", + "tags": [ + "Sessions" + ], + "summary": "Acknowledge receipt of an M→P export; API flips bartenderMode after hash verify", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HandoffAckRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Ack accepted; bartenderMode flipped from magic → passthrough", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HandoffAckSuccess" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/{session}/pair/qr": { + "get": { + "operationId": "getQRCode", + "tags": [ + "Pairing" + ], + "summary": "Get QR code for device pairing", + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `sessions:manage`\n\nDirect QR retrieval requires an explicit organization entitlement. Create a QuickLink for the standard pairing flow.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "json", + "image" + ], + "default": "json" + }, + "required": false, + "name": "format", + "in": "query" + } + ], + "responses": { + "200": { + "description": "QR code data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetQRCodeResponse" + } + }, + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Direct pairing is unavailable; create a QuickLink unless the organization has the direct-pairing entitlement", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API sessions:manage" + }, + "x-protocols": [ + "Linked Device API" + ] + } + }, + "/messaging/{session}/pair/code": { + "post": { + "operationId": "requestPairCode", + "tags": [ + "Pairing" + ], + "summary": "Request a pairing code for a phone number", + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `sessions:manage`\n\nDirect pairing-code retrieval requires an explicit organization entitlement. Create a QuickLink for the standard pairing flow.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PairCodeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Pairing code issued", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequestPairCodeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Direct pairing is unavailable; create a QuickLink unless the organization has the direct-pairing entitlement", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API sessions:manage" + }, + "x-protocols": [ + "Linked Device API" + ] + } + }, + "/messaging/{session}/messages/send": { + "post": { + "operationId": "sendMessage", + "tags": [ + "Messages" + ], + "summary": "Send a message", + "description": "**Protocols:** Linked Device API · Meta Cloud API · Polymorfa Hybrid Link\n\n**Required scope:** `messages:write`\n\nSend a message to a conversation. Put exactly one message kind inside content. Testing sessions send only to active testing numbers in the same project; supply the recipient phoneNumber.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "messages:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendMessageRequest" + }, + "example": { + "conversation": { + "phoneNumber": "+15550001111" + }, + "content": { + "text": "Hello" + } + } + } + } + }, + "responses": { + "200": { + "description": "Message sent successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendMessageResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Invalid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Invalid credential", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Missing scope or resource access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "422": { + "description": "The supplied media URL could not be fetched", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "500": { + "description": "Unexpected service failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Messaging provider failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + }, + "503": { + "description": "Session or service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + }, + "504": { + "description": "Result unknown after timeout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "result_unknown", + "message": "The result was not obtained before the deadline. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#result-unknown" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API Meta Cloud API Polymorfa Hybrid Link messages:write" + }, + "x-protocols": [ + "Linked Device API", + "Meta Cloud API", + "Polymorfa Hybrid Link" + ] + } + }, + "/messaging/{session}/messages/seen": { + "post": { + "operationId": "sendSeen", + "tags": [ + "Messages" + ], + "summary": "Mark messages as seen", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "messages:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeenRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Seen marker confirmed by the messaging backend", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageActionResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Invalid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Invalid credential", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Missing scope or resource access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Unexpected service failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Messaging provider failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + }, + "503": { + "description": "Session or service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + }, + "504": { + "description": "Result unknown after timeout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "result_unknown", + "message": "The result was not obtained before the deadline. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#result-unknown" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API Meta Cloud API Polymorfa Hybrid Link messages:write" + }, + "x-protocols": [ + "Linked Device API", + "Meta Cloud API", + "Polymorfa Hybrid Link" + ], + "description": "**Protocols:** Linked Device API · Meta Cloud API · Polymorfa Hybrid Link\n\n**Required scope:** `messages:write`" + } + }, + "/messaging/{session}/messages/typing": { + "post": { + "operationId": "setTyping", + "tags": [ + "Messages" + ], + "summary": "Set typing indicator for a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "messages:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TypingRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Typing state confirmed by the messaging backend", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageActionResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Invalid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Invalid credential", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Missing scope or resource access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Unexpected service failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Messaging provider failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + }, + "503": { + "description": "Session or service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + }, + "504": { + "description": "Result unknown after timeout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "result_unknown", + "message": "The result was not obtained before the deadline. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#result-unknown" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API messages:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `messages:write`" + } + }, + "/messaging/{session}/messages/react": { + "post": { + "operationId": "sendReaction", + "tags": [ + "Messages" + ], + "summary": "React to a message", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "messages:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReactRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Reaction sent", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendReactionResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Invalid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Invalid credential", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Missing scope or resource access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Unexpected service failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Messaging provider failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + }, + "503": { + "description": "Session or service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + }, + "504": { + "description": "Result unknown after timeout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "result_unknown", + "message": "The result was not obtained before the deadline. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#result-unknown" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API Meta Cloud API Polymorfa Hybrid Link messages:write" + }, + "x-protocols": [ + "Linked Device API", + "Meta Cloud API", + "Polymorfa Hybrid Link" + ], + "description": "**Protocols:** Linked Device API · Meta Cloud API · Polymorfa Hybrid Link\n\n**Required scope:** `messages:write`" + } + }, + "/messaging/{session}/messages/star": { + "post": { + "operationId": "starMessage", + "tags": [ + "Messages" + ], + "summary": "Star or unstar a message", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "messages:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StarRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Star status updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageActionResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Invalid request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Invalid credential", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Missing scope or resource access", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Unexpected service failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Messaging provider failure", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + }, + "503": { + "description": "Session or service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + }, + "504": { + "description": "Result unknown after timeout", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "result_unknown", + "message": "The result was not obtained before the deadline. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#result-unknown" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API messages:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `messages:write`" + } + }, + "/messaging/{session}/chats/{conversation}/messages/{messageId}": { + "put": { + "operationId": "editMessage", + "tags": [ + "Chats" + ], + "summary": "Edit a previously sent message", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "chats:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "messageId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EditMessageRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Message edited", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API chats:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `chats:manage`" + }, + "delete": { + "operationId": "deleteMessage", + "tags": [ + "Chats" + ], + "summary": "Delete a previously sent message", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "chats:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "messageId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Message deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API chats:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `chats:manage`" + } + }, + "/messaging/{session}/chats/{conversation}/archive": { + "post": { + "operationId": "archiveChat", + "tags": [ + "Chats" + ], + "summary": "Archive a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "chats:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Chat archived", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API chats:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `chats:manage`" + } + }, + "/messaging/{session}/chats/{conversation}/unarchive": { + "post": { + "operationId": "unarchiveChat", + "tags": [ + "Chats" + ], + "summary": "Unarchive a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "chats:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Chat unarchived", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API chats:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `chats:manage`" + } + }, + "/messaging/{session}/chats/{conversation}/disappearing": { + "put": { + "operationId": "setChatDisappearingTimer", + "tags": [ + "Chats" + ], + "summary": "Set the disappearing-message timer for a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "chats:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DisappearingTimerRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Disappearing-message timer updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API chats:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `chats:manage`" + } + }, + "/messaging/{session}/calls/{callId}/reject": { + "post": { + "operationId": "rejectCall", + "tags": [ + "Calls" + ], + "summary": "Reject an incoming WhatsApp call", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "chats:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "required": true, + "name": "callId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RejectCallRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Call rejected", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API chats:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `chats:manage`" + } + }, + "/messaging/voip/calls/{id}/offer": { + "post": { + "operationId": "voipOffer", + "tags": [ + "VoIP" + ], + "summary": "Submit an SDP offer and receive the pod's answer + ICE servers", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipOfferRequest" + } + } + } + }, + "responses": { + "200": { + "description": "SDP answer with STUN/TURN ICE servers", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipOfferResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "429": { + "description": "Call setup rate exceeded for this client token, or its concurrency limit is reached", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "rate_limit_error", + "code": "rate_limit_exceeded", + "message": "The request limit was reached. Follow Retry-After when supplied.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#rate-limit-exceeded" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/voip/calls/{id}/renegotiate": { + "post": { + "operationId": "voipRenegotiate", + "tags": [ + "VoIP" + ], + "summary": "Re-offer on an established call (add video, restart ICE) and receive the pod's answer", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipRenegotiateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "SDP answer for the re-offer, on the same peer connection", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipRenegotiateResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/voip/ws-ticket": { + "post": { + "operationId": "voipSocketTicket", + "tags": [ + "VoIP" + ], + "summary": "Mint a single-use ticket for the calls WebSocket", + "description": "**Required scope:** `sessions:manage`\n\nBrowsers cannot send an Authorization header on a WebSocket upgrade, so the calls socket (`GET /voip/ws?ticket=…`) is opened with a ticket obtained here. Tickets are single-use and expire after 60 seconds. Client tokens are bound to their session; server keys must name one.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipSocketTicketRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Ticket minted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipSocketTicketResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/calls/{id}/agent-token": { + "post": { + "operationId": "voipAgentToken", + "tags": [ + "VoIP" + ], + "summary": "Mint a per-call ticket for a voice agent's media WebSocket", + "description": "**Required scope:** `sessions:manage`\n\nServer keys only. The ticket is bound to this call, expires after `ttlSeconds` (default 300, max 3600) and is presented by the agent to the voip pod as `Authorization: Bearer `. It grants nothing else.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipAgentTokenRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Agent ticket minted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipAgentTokenResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/calls": { + "post": { + "operationId": "voipPlaceCall", + "tags": [ + "VoIP" + ], + "summary": "Place an outbound call from a session", + "description": "**Required scope:** `sessions:manage`\n\nOriginates a WhatsApp call to `to` (an E.164 phone number or a user ID) from the named session. The call rings on the callee's device: `call.accepted` follows when they pick up and `call.ended` when either side hangs up. Attach media like any other call — `/offer` for a browser, the SDK media socket for programmatic audio/video. Client tokens place from their bound session; server keys must name one. Outbound starts share a rate limit per organization and source session across server keys and client tokens; client-token rules also apply.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipPlaceCallRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Call placed and ringing", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipPlacedCallResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Session not ready — the named session cannot place an outbound call yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "429": { + "description": "Outbound call rate exceeded for this organization and source session, or a client-token setup or concurrency limit was reached", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "rate_limit_error", + "code": "rate_limit_exceeded", + "message": "The request limit was reached. Follow Retry-After when supplied.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#rate-limit-exceeded" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "501": { + "description": "Outbound calls are not available on this deployment", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "operation_not_supported", + "message": "This operation is not supported.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#operation-not-supported" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/calls/{id}/accept": { + "post": { + "operationId": "voipAcceptCall", + "tags": [ + "VoIP" + ], + "summary": "Answer a ringing inbound call", + "description": "**Required scope:** `sessions:manage`\n\nAnswers a call the pod is holding for the SDK (sessions in `sdk` client mode ring instead of auto-answering). 409 when the call is not ringing — already answered, ended, or hosted by a session that auto-answers.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipAcceptCallRequest" + } + } + } + }, + "responses": { + "202": { + "description": "Call answered", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/calls/{id}/reject": { + "post": { + "operationId": "voipRejectCall", + "tags": [ + "VoIP" + ], + "summary": "Decline a ringing inbound call", + "description": "**Required scope:** `sessions:manage`\n\nDeclines a call the pod is holding for the SDK and releases it. 409 when the call is not ringing.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "202": { + "description": "Call declined", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/calls/{id}/participants": { + "post": { + "operationId": "voipAddParticipant", + "tags": [ + "VoIP" + ], + "summary": "Invite another party into a live call", + "description": "**Required scope:** `sessions:manage`\n\nRings `to` (an E.164 phone number or a user ID) into the call, turning a 1:1 call into a group call. The invitee enters the roster as `invited`; roster changes reach the SDK media socket as `participant_joined` / `participant_state` / `participant_left` frames. 409 until the call has a live leg.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipAddParticipantRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Participant invited", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipAddParticipantResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "429": { + "description": "Call setup rate exceeded for this client token, or its concurrency limit is reached", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "rate_limit_error", + "code": "rate_limit_exceeded", + "message": "The request limit was reached. Follow Retry-After when supplied.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#rate-limit-exceeded" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/mode": { + "post": { + "operationId": "voipSetMode", + "tags": [ + "VoIP" + ], + "summary": "Choose how a session answers inbound calls", + "description": "**Required scope:** `sessions:manage`\n\n`browser` (default) answers each inbound call and bridges it to a browser through `/offer`; `agent` answers and bridges to the raw-audio socket; `sdk` lets the call ring and waits for your `/accept` or `/reject`. The claim persists until changed and applies to calls that arrive after it. Client tokens configure their bound session; server keys must name one.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipModeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Mode recorded", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipModeResult" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/voip/calls/{id}/candidate": { + "post": { + "operationId": "voipCandidate", + "tags": [ + "VoIP" + ], + "summary": "Trickle a local ICE candidate to the owning pod", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipCandidateRequest" + } + } + } + }, + "responses": { + "202": { + "description": "Candidate accepted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/voip/calls/{id}/candidates": { + "get": { + "operationId": "voipCandidates", + "tags": [ + "VoIP" + ], + "summary": "Poll remote ICE candidates queued for the browser", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Queued remote candidates (drained on read)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipCandidatesEnvelope" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/voip/calls/{id}": { + "delete": { + "operationId": "voipTeardown", + "tags": [ + "VoIP" + ], + "summary": "Tear down a call's browser media session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1, + "example": "call-123" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Call torn down", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Call not ready — no media session on the owning pod yet", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "410": { + "description": "Call ended — the pod that owned its media is gone (pod_lost)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_gone", + "message": "The requested retained resource has expired or was removed.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-gone" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Call unavailable — the owning pod is at capacity or draining, or call authority cannot be verified", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + }, + "description": "**Required scope:** `sessions:manage`" + } + }, + "/messaging/voip/token": { + "post": { + "operationId": "voipToken", + "tags": [ + "VoIP" + ], + "summary": "Mint a short-lived browser client token for the VoIP SDK", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scopes": [ + "sessions:manage", + "messages:write", + "contacts:read", + "presence:read", + "presence:observe", + "mcp" + ], + "x-required-scope-mode": "all", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipTokenRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Client token minted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoipTokenResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage messages:write contacts:read presence:read presence:observe mcp" + }, + "description": "**Required scopes (all):** `sessions:manage` · `messages:write` · `contacts:read` · `presence:read` · `presence:observe` · `mcp`" + } + }, + "/messaging/{session}/groups": { + "get": { + "operationId": "listGroups", + "tags": [ + "Groups" + ], + "summary": "List groups the session is a member of", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Group list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListGroupsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:read`" + }, + "post": { + "operationId": "createGroup", + "tags": [ + "Groups" + ], + "summary": "Create a new group", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGroupRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Group created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateGroupResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/join-info": { + "get": { + "operationId": "getGroupJoinInfo", + "tags": [ + "Groups" + ], + "summary": "Look up group info for an invite code", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 1 + }, + "required": true, + "name": "code", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Join info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetGroupJoinInfoResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:read`" + } + }, + "/messaging/{session}/groups/join": { + "post": { + "operationId": "joinGroup", + "tags": [ + "Groups" + ], + "summary": "Join a group by invite code", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JoinGroupRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Joined group", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}": { + "get": { + "operationId": "getGroup", + "tags": [ + "Groups" + ], + "summary": "Get group details", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Group details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetGroupResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:read`" + }, + "delete": { + "operationId": "deleteGroup", + "tags": [ + "Groups" + ], + "summary": "Leave a group (DELETE alias)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Left group", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/leave": { + "post": { + "operationId": "leaveGroup", + "tags": [ + "Groups" + ], + "summary": "Leave a group", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Left group", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/subject": { + "put": { + "operationId": "setGroupSubject", + "tags": [ + "Groups" + ], + "summary": "Set group subject (name)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetGroupFieldRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Subject updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/description": { + "put": { + "operationId": "setGroupDescription", + "tags": [ + "Groups" + ], + "summary": "Set group description", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetGroupFieldRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Description updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/invite-code": { + "get": { + "operationId": "getGroupInviteCode", + "tags": [ + "Groups" + ], + "summary": "Get the current group invite code", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Invite code", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetGroupInviteCodeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:read`" + } + }, + "/messaging/{session}/groups/{id}/invite-code/revoke": { + "post": { + "operationId": "revokeGroupInviteCode", + "tags": [ + "Groups" + ], + "summary": "Revoke the current invite code and generate a new one", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "New invite code", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RevokeGroupInviteCodeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/participants": { + "get": { + "operationId": "getGroupParticipants", + "tags": [ + "Groups" + ], + "summary": "List group participants", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Participant list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetGroupParticipantsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:read`" + } + }, + "/messaging/{session}/groups/{id}/participants/add": { + "post": { + "operationId": "addGroupParticipants", + "tags": [ + "Groups" + ], + "summary": "Add participants to a group", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Participants added", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/participants/remove": { + "post": { + "operationId": "removeGroupParticipants", + "tags": [ + "Groups" + ], + "summary": "Remove participants from a group", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Participants removed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/admin/promote": { + "post": { + "operationId": "promoteGroupAdmin", + "tags": [ + "Groups" + ], + "summary": "Promote participants to admin", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Participants promoted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/admin/demote": { + "post": { + "operationId": "demoteGroupAdmin", + "tags": [ + "Groups" + ], + "summary": "Demote admin participants", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupParticipantsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Participants demoted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/picture": { + "put": { + "operationId": "setGroupPicture", + "tags": [ + "Groups" + ], + "summary": "Set the group profile picture", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetGroupPictureRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Picture updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/settings/info-edit": { + "put": { + "operationId": "setGroupInfoEditing", + "tags": [ + "Groups" + ], + "summary": "Choose who can edit group information", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupAdminOnlySettingRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Group information permission updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/settings/messages": { + "put": { + "operationId": "setGroupMessaging", + "tags": [ + "Groups" + ], + "summary": "Choose who can send group messages", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupAdminOnlySettingRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Group messaging permission updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/settings/member-add": { + "put": { + "operationId": "setGroupMemberAddMode", + "tags": [ + "Groups" + ], + "summary": "Choose who can add group members", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupMemberAddModeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Group member-add mode updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/groups/{id}/settings/join-approval": { + "put": { + "operationId": "setGroupJoinApproval", + "tags": [ + "Groups" + ], + "summary": "Require admin approval for invite-link joins", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "groups:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_gid_[0-9]+(?:-[0-9]+)?$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupJoinApprovalRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Group join approval updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API groups:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `groups:manage`" + } + }, + "/messaging/{session}/contacts": { + "get": { + "operationId": "listContacts", + "tags": [ + "Contacts" + ], + "summary": "List all contacts known to the session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Contact list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListContactsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/check": { + "get": { + "operationId": "checkContacts", + "tags": [ + "Contacts" + ], + "summary": "Check if phone numbers are registered on WhatsApp", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "required": true, + "name": "phone", + "in": "query", + "style": "form", + "explode": false + } + ], + "responses": { + "200": { + "description": "Contact check results", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CheckContactsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/blocked": { + "get": { + "operationId": "getBlocklist", + "tags": [ + "Contacts" + ], + "summary": "Get blocked contacts", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Blocked contacts", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBlocklistResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/{contactId}": { + "get": { + "operationId": "getContact", + "tags": [ + "Contacts" + ], + "summary": "Get a contact by stable user ID", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Contact details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetContactResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/{contactId}/picture": { + "get": { + "operationId": "getContactPicture", + "tags": [ + "Contacts" + ], + "summary": "Get a contact's profile picture URL", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Profile picture URL", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetContactPictureResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/{contactId}/info": { + "get": { + "operationId": "getUserInfo", + "tags": [ + "Contacts" + ], + "summary": "Get live WhatsApp user metadata", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "User metadata", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetUserInfoResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/{contactId}/devices": { + "get": { + "operationId": "getUserDevices", + "tags": [ + "Contacts" + ], + "summary": "Get a contact's linked devices", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Linked devices", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetUserDevicesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/{contactId}/business-profile": { + "get": { + "operationId": "getBusinessProfile", + "tags": [ + "Contacts" + ], + "summary": "Get a WhatsApp business profile", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Business profile", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessProfileResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/contacts/{contactId}/block": { + "post": { + "operationId": "blockContact", + "tags": [ + "Contacts" + ], + "summary": "Block a contact", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Contact blocked", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:manage`" + } + }, + "/messaging/{session}/contacts/{contactId}/unblock": { + "post": { + "operationId": "unblockContact", + "tags": [ + "Contacts" + ], + "summary": "Unblock a contact", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_(?:lid|botid)_[1-9]\\d*$" + }, + "required": true, + "name": "contactId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Contact unblocked", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:manage`" + } + }, + "/messaging/{session}/business/linked-accounts": { + "get": { + "operationId": "getBusinessLinkedAccounts", + "tags": [ + "Business App" + ], + "summary": "Read live accounts linked to the connected WhatsApp Business App", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Live linked-account state", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessLinkedAccountsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + } + }, + "/messaging/{session}/business/eligibility": { + "get": { + "operationId": "getBusinessEligibility", + "tags": [ + "Business App" + ], + "summary": "Read live feature eligibility for the connected WhatsApp Business App", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Live business feature eligibility", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessEligibilityResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + } + }, + "/messaging/{session}/business/profile": { + "get": { + "operationId": "getOwnBusinessProfile", + "tags": [ + "Business App" + ], + "summary": "Read the connected WhatsApp Business App profile", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Live business profile", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetOwnBusinessProfileResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:read`" + }, + "patch": { + "operationId": "updateBusinessProfile", + "tags": [ + "Business App" + ], + "summary": "Update the connected WhatsApp Business App profile", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessProfileUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Profile updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateBusinessProfileResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/profile/cover-photo": { + "put": { + "operationId": "setBusinessCoverPhoto", + "tags": [ + "Business App" + ], + "summary": "Set the connected WhatsApp Business App cover photo", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCoverPhotoRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Cover photo set", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetBusinessCoverPhotoResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/profile/cover-photo/{coverPhotoId}": { + "delete": { + "operationId": "deleteBusinessCoverPhoto", + "tags": [ + "Business App" + ], + "summary": "Delete the connected WhatsApp Business App cover photo", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "required": true, + "name": "coverPhotoId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Cover photo removed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteBusinessCoverPhotoResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/compliance": { + "get": { + "operationId": "getBusinessMerchantCompliance", + "tags": [ + "Business App" + ], + "summary": "Read merchant compliance details for the connected WhatsApp Business App account", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Live merchant compliance details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessMerchantComplianceResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:read`" + }, + "put": { + "operationId": "setBusinessMerchantCompliance", + "tags": [ + "Business App" + ], + "summary": "Replace merchant compliance details for the connected WhatsApp Business App account", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessMerchantCompliance" + } + } + } + }, + "responses": { + "200": { + "description": "Merchant compliance details updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetBusinessMerchantComplianceResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/quick-replies": { + "post": { + "operationId": "createBusinessQuickReply", + "tags": [ + "Business App" + ], + "summary": "Create a WhatsApp Business App quick reply", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessQuickReplyMutation" + } + } + } + }, + "responses": { + "200": { + "description": "Quick reply created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBusinessQuickReplyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + }, + "get": { + "operationId": "listBusinessQuickReplies", + "tags": [ + "Business App" + ], + "summary": "List remembered WhatsApp Business App quick replies", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Best-effort quick reply list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListBusinessQuickRepliesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:read`" + } + }, + "/messaging/{session}/business/quick-replies/{quickReplyId}": { + "put": { + "operationId": "setBusinessQuickReply", + "tags": [ + "Business App" + ], + "summary": "Replace a WhatsApp Business App quick reply", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 20, + "pattern": "^[0-9]+$" + }, + "required": true, + "name": "quickReplyId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessQuickReplyMutation" + } + } + } + }, + "responses": { + "200": { + "description": "Quick reply replaced", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetBusinessQuickReplyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + }, + "delete": { + "operationId": "deleteBusinessQuickReply", + "tags": [ + "Business App" + ], + "summary": "Delete a WhatsApp Business App quick reply", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 20, + "pattern": "^[0-9]+$" + }, + "required": true, + "name": "quickReplyId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Quick reply deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteBusinessQuickReplyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/catalog": { + "get": { + "operationId": "getBusinessCatalog", + "tags": [ + "Business App" + ], + "summary": "Read a WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256, + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "required": true, + "name": "id", + "in": "query" + }, + { + "schema": { + "type": "string", + "maxLength": 2048 + }, + "required": false, + "name": "after", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100 + }, + "required": false, + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "required": false, + "name": "width", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "required": false, + "name": "height", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Live catalog page", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessCatalogResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Upstream WhatsApp request failed or its response could not be mapped", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + }, + "post": { + "operationId": "createBusinessCatalog", + "tags": [ + "Business App" + ], + "summary": "Create a catalog for the connected WhatsApp Business App account", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Catalog created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBusinessCatalogResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/catalog/cart": { + "patch": { + "operationId": "setBusinessCartEnabled", + "tags": [ + "Business App" + ], + "summary": "Enable or disable the connected WhatsApp Business App catalog cart", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCartSettingRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Cart setting updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetBusinessCartEnabledResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/products/{productId}": { + "get": { + "operationId": "getBusinessProduct", + "tags": [ + "Business App" + ], + "summary": "Read a WhatsApp Business App product", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "productId", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256, + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "required": true, + "name": "id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Live product", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessProductResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Upstream WhatsApp request failed or its response could not be mapped", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + }, + "put": { + "operationId": "updateBusinessProduct", + "tags": [ + "Business App" + ], + "summary": "Replace a product in the connected WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "productId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessProductMutationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Product updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateBusinessProductResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + }, + "delete": { + "operationId": "deleteBusinessProduct", + "tags": [ + "Business App" + ], + "summary": "Delete a product from the connected WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "productId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Product deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteBusinessProductResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/products": { + "post": { + "operationId": "createBusinessProduct", + "tags": [ + "Business App" + ], + "summary": "Create a product in the connected WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessProductMutationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Product created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBusinessProductResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/products/{productId}/visibility": { + "patch": { + "operationId": "setBusinessProductVisibility", + "tags": [ + "Business App" + ], + "summary": "Hide or show a product in the connected WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "productId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessProductVisibilityRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Product visibility updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetBusinessProductVisibilityResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/products/{productId}/appeal": { + "post": { + "operationId": "appealBusinessProduct", + "tags": [ + "Business App" + ], + "summary": "Request a review of a rejected WhatsApp Business App catalog product", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "productId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCatalogAppealRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Product appeal submitted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AppealBusinessProductResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/collections": { + "get": { + "operationId": "getBusinessCollections", + "tags": [ + "Business App" + ], + "summary": "Read WhatsApp Business App collections", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256, + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "required": true, + "name": "id", + "in": "query" + }, + { + "schema": { + "type": "string", + "maxLength": 2048 + }, + "required": false, + "name": "after", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 20 + }, + "required": false, + "name": "collectionLimit", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100 + }, + "required": false, + "name": "itemLimit", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "required": false, + "name": "width", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "required": false, + "name": "height", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Live collection page", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessCollectionsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Upstream WhatsApp request failed or its response could not be mapped", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + }, + "post": { + "operationId": "createBusinessCollection", + "tags": [ + "Business App" + ], + "summary": "Create a collection in the connected WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCollectionCreateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Collection created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBusinessCollectionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/collections/{collectionId}": { + "get": { + "operationId": "getBusinessCollection", + "tags": [ + "Business App" + ], + "summary": "Read a WhatsApp Business App collection", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "collectionId", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256, + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "required": true, + "name": "id", + "in": "query" + }, + { + "schema": { + "type": "string", + "maxLength": 2048 + }, + "required": false, + "name": "after", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100 + }, + "required": false, + "name": "limit", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "required": false, + "name": "width", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1024 + }, + "required": false, + "name": "height", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Live collection", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessCollectionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Upstream WhatsApp request failed or its response could not be mapped", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + }, + "patch": { + "operationId": "updateBusinessCollection", + "tags": [ + "Business App" + ], + "summary": "Update a collection and its product membership", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "collectionId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCollectionUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Collection updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateBusinessCollectionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + }, + "delete": { + "operationId": "deleteBusinessCollection", + "tags": [ + "Business App" + ], + "summary": "Delete a collection from the connected WhatsApp Business App catalog", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "collectionId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Collection deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteBusinessCollectionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/collections/reorder": { + "post": { + "operationId": "reorderBusinessCollections", + "tags": [ + "Business App" + ], + "summary": "Reorder connected WhatsApp Business App catalog collections", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCollectionReorderRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Collections reordered", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReorderBusinessCollectionsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/collections/{collectionId}/appeal": { + "post": { + "operationId": "appealBusinessCollection", + "tags": [ + "Business App" + ], + "summary": "Request a review of a rejected WhatsApp Business App catalog collection", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "collectionId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessCatalogAppealRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Collection appeal submitted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AppealBusinessCollectionResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/business/orders/{orderId}/lookup": { + "post": { + "operationId": "getBusinessOrder", + "tags": [ + "Business App" + ], + "summary": "Read WhatsApp Business App order details", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "business:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "maxLength": 256 + }, + "required": true, + "name": "orderId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessOrderLookupRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Order details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBusinessOrderResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Upstream WhatsApp request failed or its response could not be mapped", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API business:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `business:read`" + } + }, + "/messaging/{session}/identities/resolve": { + "get": { + "operationId": "resolveIdentity", + "tags": [ + "Identities" + ], + "summary": "Resolve a user alias to a stable user ID", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": false, + "name": "phoneNumber", + "in": "query" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "required": false, + "name": "id", + "in": "query" + }, + { + "schema": { + "type": "string", + "minLength": 3, + "maxLength": 35 + }, + "required": false, + "name": "username", + "in": "query" + }, + { + "schema": { + "type": "string", + "pattern": "^\\d{4}$" + }, + "required": false, + "name": "usernameKey", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Stable user ID and known aliases", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResolveIdentityResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/users/{id}/security-code": { + "get": { + "operationId": "getUserSecurityCode", + "tags": [ + "Users" + ], + "summary": "Get an identity verification code for a user", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "contacts:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "pattern": "^pmfa_lid_[1-9]\\d*$" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Identity verification code and display QR", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSecurityCodeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API contacts:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `contacts:read`" + } + }, + "/messaging/{session}/channels": { + "get": { + "operationId": "listChannels", + "tags": [ + "Channels" + ], + "summary": "List channels the session follows", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListChannelsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:read`" + }, + "post": { + "operationId": "createChannel", + "tags": [ + "Channels" + ], + "summary": "Create a new channel", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChannelRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Channel created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChannelResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}": { + "get": { + "operationId": "getChannel", + "tags": [ + "Channels" + ], + "summary": "Get channel details", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChannelResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:read`" + }, + "delete": { + "operationId": "deleteChannel", + "tags": [ + "Channels" + ], + "summary": "Delete a channel", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteChannelResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "502": { + "description": "Upstream WhatsApp request failed or its response could not be mapped", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "upstream_error", + "code": "upstream_failure", + "message": "The messaging provider could not complete the request.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#upstream-failure" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}/messages": { + "get": { + "operationId": "listChannelMessages", + "tags": [ + "Channels" + ], + "summary": "List channel messages", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "required": false, + "name": "count", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "required": false, + "name": "before", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Channel messages", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListChannelMessagesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:read`" + } + }, + "/messaging/{session}/channels/{id}/message-updates": { + "get": { + "operationId": "listChannelMessageUpdates", + "tags": [ + "Channels" + ], + "summary": "List channel view and reaction updates", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "required": false, + "name": "count", + "in": "query" + }, + { + "schema": { + "type": "integer", + "nullable": true, + "minimum": 0 + }, + "required": false, + "name": "since", + "in": "query" + }, + { + "schema": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "required": false, + "name": "after", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Channel message updates", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListChannelMessageUpdatesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:read`" + } + }, + "/messaging/{session}/channels/{id}/messages/{serverId}/viewed": { + "post": { + "operationId": "markChannelMessageViewed", + "tags": [ + "Channels" + ], + "summary": "Mark a channel message as viewed", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "required": true, + "name": "serverId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Message marked viewed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}/messages/{serverId}/reaction": { + "post": { + "operationId": "reactToChannelMessage", + "tags": [ + "Channels" + ], + "summary": "React to a channel message", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + }, + { + "schema": { + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true + }, + "required": true, + "name": "serverId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelReactionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Reaction updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}/live-updates": { + "post": { + "operationId": "subscribeChannelLiveUpdates", + "tags": [ + "Channels" + ], + "summary": "Subscribe temporarily to channel live updates", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Live-update subscription duration", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelLiveUpdatesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:read`" + } + }, + "/messaging/{session}/channels/{id}/follow": { + "post": { + "operationId": "followChannel", + "tags": [ + "Channels" + ], + "summary": "Follow a channel", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel followed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}/unfollow": { + "post": { + "operationId": "unfollowChannel", + "tags": [ + "Channels" + ], + "summary": "Unfollow a channel", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel unfollowed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}/mute": { + "post": { + "operationId": "muteChannel", + "tags": [ + "Channels" + ], + "summary": "Mute a channel", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel muted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/channels/{id}/unmute": { + "post": { + "operationId": "unmuteChannel", + "tags": [ + "Channels" + ], + "summary": "Unmute a channel", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "channels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Channel unmuted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API channels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `channels:manage`" + } + }, + "/messaging/{session}/presence": { + "post": { + "operationId": "setPresence", + "tags": [ + "Presence" + ], + "summary": "Set the session's own presence (available / unavailable)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetPresenceRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Presence updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API presence:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `presence:write`" + }, + "get": { + "operationId": "getPresence", + "tags": [ + "Presence" + ], + "summary": "Get the session's own presence", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Presence info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetPresenceResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API presence:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `presence:read`" + } + }, + "/messaging/{session}/presence/{conversation}": { + "get": { + "operationId": "getChatPresence", + "tags": [ + "Presence" + ], + "summary": "Get presence for a specific chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Chat presence", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatPresenceResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API presence:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `presence:read`" + } + }, + "/messaging/{session}/presence/{conversation}/subscribe": { + "post": { + "operationId": "subscribePresence", + "tags": [ + "Presence" + ], + "summary": "Subscribe to presence updates for a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:observe", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Subscribed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscribePresenceResponse" + } + } + } + }, + "202": { + "description": "Accepted for asynchronous processing in response to `Prefer: respond-async`; the result is not included", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AsyncAcceptedResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "429": { + "description": "Observation limit exceeded, or the session is inside the suspension window that follows", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "rate_limit_error", + "code": "rate_limit_exceeded", + "message": "The request limit was reached. Follow Retry-After when supplied.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#rate-limit-exceeded" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API presence:observe" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `presence:observe`" + } + }, + "/messaging/projects/{projectId}/safe-mode": { + "get": { + "operationId": "getProjectSafeMode", + "tags": [ + "Safe Mode" + ], + "summary": "Get a project's Safe Mode ceiling", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Project Safe Mode ceiling, and whether the plan includes BanSafe Lite", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProjectSafeModeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + }, + "description": "**Required scope:** `sessions:read`" + }, + "put": { + "operationId": "updateProjectSafeMode", + "tags": [ + "Safe Mode" + ], + "summary": "Set a project's Safe Mode ceiling", + "description": "**Required scope:** `sessions:manage`\n\nSets the most visible behaviour any number in this project may use. Presence and read receipts are visible to the people this number messages: turning them on makes the number appear online, exposes last-seen subject to the account's privacy settings, and puts blue ticks on incoming messages. Every axis is off by default and only this request changes it.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "off", + "jittered", + "conversation" + ] + }, + "onlineStart": { + "type": "integer", + "minimum": 0, + "maximum": 23 + }, + "onlineEnd": { + "type": "integer", + "minimum": 0, + "maximum": 23 + } + }, + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "Project Safe Mode ceiling updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectSafeModeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "Safe Mode is part of BanSafe Lite, which is not included on this number's plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Stored, but a connected number did not confirm the policy; retry the request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/{session}/safe-mode": { + "get": { + "operationId": "getSessionSafeMode", + "tags": [ + "Safe Mode" + ], + "summary": "Get a number's effective Safe Mode", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1 + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Project ceiling, number override, the effective policy, and whether the plan includes BanSafe Lite", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetSessionSafeModeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API sessions:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `sessions:read`" + }, + "put": { + "operationId": "updateSessionSafeMode", + "tags": [ + "Safe Mode" + ], + "summary": "Set a number's Safe Mode override", + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `sessions:manage`\n\nSets one number's Safe Mode. Each axis accepts `inherit` to follow the project ceiling. An override may only be equally or more conservative than the ceiling; a more visible value is refused with `safe_mode_exceeds_project_ceiling`.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1 + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "presence": { + "type": "string", + "enum": [ + "inherit", + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "inherit", + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "inherit", + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "inherit", + "off", + "jittered", + "conversation" + ] + } + }, + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "Number Safe Mode override updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSessionSafeModeResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "Safe Mode is part of BanSafe Lite, which is not included on this number's plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Stored, but a connected number did not confirm the policy; retry the request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API sessions:manage" + }, + "x-protocols": [ + "Linked Device API" + ] + } + }, + "/messaging/projects/{projectId}/warmup-plan": { + "get": { + "operationId": "getProjectWarmupPlan", + "tags": [ + "Warm-up plan" + ], + "summary": "Get a project's warm-up plan", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Project warm-up plan, its projected curve, and whether the plan includes BanSafe Lite", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProjectWarmupPlanResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + }, + "description": "**Required scope:** `sessions:read`" + }, + "put": { + "operationId": "updateProjectWarmupPlan", + "tags": [ + "Warm-up plan" + ], + "summary": "Set a project's warm-up plan", + "description": "**Required scope:** `sessions:manage`\n\nTurns the warm-up plan on or off for a project and sets how long the ramp takes and how many messages a number may send on its first day. While the plan is on, a send past a number's allowance is refused with `bansafe_daily_allowance_reached` and campaign recipients are deferred to the next reset.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "warmupDays": { + "type": "integer", + "minimum": 1, + "maximum": 90 + }, + "dailyStart": { + "type": "integer", + "minimum": 1, + "maximum": 2000 + } + }, + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "Project warm-up plan updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectWarmupPlanResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "The warm-up plan is part of BanSafe Lite, which is not included on this project's plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Stored, but a connected number did not confirm the plan; retry the request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/projects/{projectId}/health-policy": { + "get": { + "operationId": "getProjectHealthPolicy", + "tags": [ + "BanSafe" + ], + "summary": "Get a project's health policy", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Project health threshold and configured actions", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProjectHealthPolicyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + }, + "description": "**Required scope:** `sessions:read`" + }, + "put": { + "operationId": "updateProjectHealthPolicy", + "tags": [ + "BanSafe" + ], + "summary": "Set a project's health policy", + "description": "**Required scope:** `sessions:manage`\n\nReplaces the project policy when version matches the stored version. The rule triggers only when an available health estimate is below threshold. Stopping disconnects a session while retaining its linked credentials; logging out requires relinking.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectHealthPolicyInput" + } + } + } + }, + "responses": { + "200": { + "description": "Project health policy updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectHealthPolicyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Version conflict or selected notification integration unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/projects/{projectId}/insurance-evidence": { + "get": { + "operationId": "getProjectInsuranceEvidence", + "tags": [ + "Ban insurance" + ], + "summary": "Get ban insurance evidence setting", + "description": "**Required scope:** `sessions:read`\n\nBan insurance evidence lets Polymorfa measure what the other devices linked to a number do with it: how many messages they send, to how many people, how fast, and in which hours. Only counts are kept, never messages, contacts, or device names. With it off, a claim can still be filed, but Polymorfa cannot say whether another device caused the ban and a person decides the claim.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:read", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "The project's ban insurance evidence setting", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProjectInsuranceEvidenceResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "sessions:read" + } + }, + "put": { + "operationId": "updateProjectInsuranceEvidence", + "tags": [ + "Ban insurance" + ], + "summary": "Set ban insurance evidence setting", + "description": "**Required scope:** `sessions:manage`\n\nBan insurance evidence lets Polymorfa measure what the other devices linked to a number do with it: how many messages they send, to how many people, how fast, and in which hours. Only counts are kept, never messages, contacts, or device names. With it off, a claim can still be filed, but Polymorfa cannot say whether another device caused the ban and a person decides the claim.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "sessions:manage", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "The project's ban insurance evidence setting was updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectInsuranceEvidenceResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Stored, but a connected number did not confirm the change; retry the request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "sessions:manage" + } + } + }, + "/messaging/projects/{projectId}/observation-policy": { + "get": { + "operationId": "getProjectObservationPolicy", + "tags": [ + "Presence", + "Labels", + "Business App" + ], + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:read", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Project observation ceiling", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProjectObservationPolicyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "presence:read" + }, + "description": "**Required scope:** `presence:read`" + }, + "put": { + "operationId": "updateProjectObservationPolicy", + "tags": [ + "Presence", + "Labels", + "Business App" + ], + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:observe", + "parameters": [ + { + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "name": "projectId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "presenceMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "typingMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + }, + "labelMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache", + "project" + ] + }, + "quickReplyMode": { + "type": "string", + "enum": [ + "off", + "events", + "cache" + ] + } + }, + "required": [ + "presenceMode", + "typingMode" + ], + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "Project observation ceiling updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectObservationPolicyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Label projection cleanup is active or failed; resolve failed cleanup before re-enabling project retention", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Policy was stored but a connected runner did not acknowledge it; retry the request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "presence:observe" + }, + "description": "**Required scope:** `presence:observe`" + } + }, + "/messaging/{session}/observation-policy": { + "get": { + "operationId": "getSessionObservationPolicy", + "tags": [ + "Presence", + "Labels", + "Business App" + ], + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:read", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1 + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Effective session observation policy", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetSessionObservationPolicyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API presence:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `presence:read`" + }, + "put": { + "operationId": "updateSessionObservationPolicy", + "tags": [ + "Presence", + "Labels", + "Business App" + ], + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "presence:observe", + "parameters": [ + { + "schema": { + "type": "string", + "minLength": 1 + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "presenceMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache" + ] + }, + "typingMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache" + ] + }, + "labelMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache", + "project" + ] + }, + "quickReplyMode": { + "type": "string", + "enum": [ + "inherit", + "off", + "events", + "cache" + ] + } + }, + "required": [ + "presenceMode", + "typingMode" + ], + "additionalProperties": false + } + } + } + }, + "responses": { + "200": { + "description": "Session observation override updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSessionObservationPolicyResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "Label projection cleanup is active or failed; resolve failed cleanup before re-enabling project retention", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + }, + "503": { + "description": "Policy was stored but a connected runner did not acknowledge it; retry the request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "service_unavailable", + "message": "A required service is unavailable. Check completion before repeating a write.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#service-unavailable" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API presence:observe" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `presence:observe`" + } + }, + "/messaging/{session}/profile": { + "get": { + "operationId": "getProfile", + "tags": [ + "Profile" + ], + "summary": "Get the session's own profile", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Profile info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProfileResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:read`" + } + }, + "/messaging/{session}/profile/name": { + "put": { + "operationId": "setProfileName", + "tags": [ + "Profile" + ], + "summary": "Set profile display name (push name)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetProfileNameRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Name updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/profile/status": { + "put": { + "operationId": "setProfileStatus", + "tags": [ + "Profile" + ], + "summary": "Set profile status (about) text", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetProfileStatusRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Status updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/profile/picture": { + "put": { + "operationId": "setProfilePicture", + "tags": [ + "Profile" + ], + "summary": "Set profile picture", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetProfilePictureRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Picture updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + }, + "delete": { + "operationId": "deleteProfilePicture", + "tags": [ + "Profile" + ], + "summary": "Remove the profile picture", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Picture deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/privacy": { + "get": { + "operationId": "getPrivacySettings", + "tags": [ + "Privacy" + ], + "summary": "Get privacy settings", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Privacy settings", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PrivacySettingsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:read`" + } + }, + "/messaging/{session}/privacy/disappearing/default": { + "put": { + "operationId": "setDefaultDisappearingTimer", + "tags": [ + "Privacy" + ], + "summary": "Set the default disappearing-message timer", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultDisappearingTimerRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Default disappearing-message timer updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/privacy/{setting}": { + "put": { + "operationId": "setPrivacySetting", + "tags": [ + "Privacy" + ], + "summary": "Update a privacy setting", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "profile:write", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "groupadd", + "last", + "status", + "profile", + "readreceipts", + "online", + "calladd", + "messages", + "defense", + "stickers" + ] + }, + "required": true, + "name": "setting", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetPrivacySettingRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Updated privacy settings", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatedPrivacySettingsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API profile:write" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `profile:write`" + } + }, + "/messaging/{session}/labels": { + "get": { + "operationId": "listLabels", + "tags": [ + "Labels" + ], + "summary": "List labels defined for the session", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "labels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "required": false, + "name": "includeObservation", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Label list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListLabelsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API labels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `labels:read`" + }, + "post": { + "operationId": "createLabel", + "tags": [ + "Labels" + ], + "summary": "Create a label", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "labels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLabelRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Label created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLabelResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API labels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `labels:manage`" + } + }, + "/messaging/{session}/labels/{labelId}": { + "put": { + "operationId": "updateLabel", + "tags": [ + "Labels" + ], + "summary": "Update a label", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "labels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "labelId", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateLabelRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Label updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "The session has no authoritative view of its labels yet. Retry once a cached or project-retained snapshot is complete.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API labels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `labels:manage`" + }, + "delete": { + "operationId": "deleteLabel", + "tags": [ + "Labels" + ], + "summary": "Delete a label", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "labels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "labelId", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Label deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API labels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `labels:manage`" + } + }, + "/messaging/{session}/labels/chats/{conversation}": { + "get": { + "operationId": "getChatLabels", + "tags": [ + "Labels" + ], + "summary": "Get labels attached to a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "labels:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + }, + { + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "required": false, + "name": "includeObservation", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Chat labels", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetChatLabelsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API labels:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `labels:read`" + }, + "put": { + "operationId": "setChatLabels", + "tags": [ + "Labels" + ], + "summary": "Replace the set of labels attached to a chat", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "labels:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "session", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "conversation", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetChatLabelsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Chat labels updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "409": { + "description": "The session has no authoritative view of its labels yet. Retry once a cached or project-retained snapshot is complete.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "conflict_error", + "code": "state_conflict", + "message": "The request conflicts with the resource state.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#state-conflict" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API labels:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `labels:manage`" + } + }, + "/messaging/webhooks": { + "get": { + "operationId": "listWebhooks", + "tags": [ + "Webhooks" + ], + "summary": "List webhooks for the tenant", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "webhooks:manage", + "responses": { + "200": { + "description": "Webhook list", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListWebhooksResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "webhooks:manage" + }, + "description": "**Required scope:** `webhooks:manage`" + }, + "post": { + "operationId": "createWebhook", + "tags": [ + "Webhooks" + ], + "summary": "Register a new webhook", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "webhooks:manage", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWebhookRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Webhook created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateWebhookResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "webhooks:manage" + }, + "description": "**Required scope:** `webhooks:manage`" + } + }, + "/messaging/webhooks/{id}": { + "get": { + "operationId": "getWebhook", + "tags": [ + "Webhooks" + ], + "summary": "Get a webhook by id", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "webhooks:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Webhook details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetWebhookResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "webhooks:manage" + }, + "description": "**Required scope:** `webhooks:manage`" + }, + "put": { + "operationId": "updateWebhook", + "tags": [ + "Webhooks" + ], + "summary": "Update a webhook", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "webhooks:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateWebhookRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Webhook updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateWebhookResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "webhooks:manage" + }, + "description": "**Required scope:** `webhooks:manage`" + }, + "delete": { + "operationId": "deleteWebhook", + "tags": [ + "Webhooks" + ], + "summary": "Delete a webhook", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "webhooks:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Webhook deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "webhooks:manage" + }, + "description": "**Required scope:** `webhooks:manage`" + } + }, + "/messaging/media/{id}": { + "get": { + "operationId": "downloadMedia", + "tags": [ + "Media" + ], + "summary": "Download media (binary stream or redirect to S3)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "media:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Media binary stream" + }, + "302": { + "description": "Redirect to S3" + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API media:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `media:read`" + } + }, + "/messaging/media/{id}/info": { + "get": { + "operationId": "getMediaInfo", + "tags": [ + "Media" + ], + "summary": "Get media metadata", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "media:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Media info", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetMediaInfoResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API media:read" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `media:read`" + } + }, + "/messaging/media/{id}/download-and-save": { + "post": { + "operationId": "downloadAndSaveMedia", + "tags": [ + "Media" + ], + "summary": "Download media and persist it to the tenant's S3 bucket", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "media:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Persistence queued or already persisted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "Linked Device API media:manage" + }, + "x-protocols": [ + "Linked Device API" + ], + "description": "**Protocols:** Linked Device API\n\n**Required scope:** `media:manage`" + } + }, + "/messaging/projects/{projectSlug}/templates": { + "get": { + "operationId": "listProjectTemplates", + "tags": [ + "Templates" + ], + "summary": "List project message templates", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Templates", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListProjectTemplatesResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:read" + }, + "description": "**Required scope:** `templates:read`" + }, + "post": { + "operationId": "createProjectTemplate", + "tags": [ + "Templates" + ], + "summary": "Create a project message template", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMessageTemplateRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectTemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:manage" + }, + "description": "**Required scope:** `templates:manage`" + } + }, + "/messaging/projects/{projectSlug}/templates/{id}": { + "get": { + "operationId": "getProjectTemplate", + "tags": [ + "Templates" + ], + "summary": "Get a project message template", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Template", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetProjectTemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:read" + }, + "description": "**Required scope:** `templates:read`" + }, + "patch": { + "operationId": "updateProjectTemplate", + "tags": [ + "Templates" + ], + "summary": "Update a project message template", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateMessageTemplateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectTemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:manage" + }, + "description": "**Required scope:** `templates:manage`" + }, + "delete": { + "operationId": "deleteProjectTemplate", + "tags": [ + "Templates" + ], + "summary": "Delete a project message template", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SuccessResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:manage" + }, + "description": "**Required scope:** `templates:manage`" + } + }, + "/messaging/projects/{projectSlug}/templates/{id}/preview": { + "post": { + "operationId": "previewProjectTemplate", + "tags": [ + "Templates" + ], + "summary": "Render a template preview (idealized) or surface-specific output", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PreviewMessageTemplateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Rendered", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PreviewProjectTemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:read" + }, + "description": "**Required scope:** `templates:read`" + } + }, + "/messaging/projects/{projectSlug}/templates/{id}/submit": { + "post": { + "operationId": "submitProjectTemplateToMeta", + "tags": [ + "Templates" + ], + "summary": "Submit a project template to Meta for approval on a Cloud-API session", + "description": "**Required scope:** `templates:manage`\n\nRenders the canonical template into a Meta create-template payload and submits it through the given cloud_api session. Records a per-session approval pointer (cloudLinks) and returns the updated template. The Meta review verdict arrives later via webhook.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "templates:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubmitMessageTemplateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Submitted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubmitProjectTemplateResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "templates:manage" + } + } + }, + "/messaging/projects/{projectSlug}/campaigns": { + "get": { + "operationId": "listCampaigns", + "tags": [ + "Campaigns" + ], + "summary": "List campaigns", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListCampaignsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:read" + }, + "description": "**Required scope:** `campaigns:read`" + }, + "post": { + "operationId": "createCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Create a campaign", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCampaignRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:manage" + }, + "description": "**Required scope:** `campaigns:manage`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}": { + "get": { + "operationId": "getCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Get a campaign", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:read" + }, + "description": "**Required scope:** `campaigns:read`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}/analytics": { + "get": { + "operationId": "getCampaignAnalytics", + "tags": [ + "Campaigns" + ], + "summary": "Campaign analytics (funnel, response timing, retries)", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:read", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignAnalyticsResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:read" + }, + "description": "**Required scope:** `campaigns:read`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}/launch": { + "post": { + "operationId": "launchCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Launch a campaign", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LaunchCampaignRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LaunchCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:manage" + }, + "description": "**Required scope:** `campaigns:manage`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}/pause": { + "post": { + "operationId": "pauseCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Pause a campaign", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PauseCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:manage" + }, + "description": "**Required scope:** `campaigns:manage`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}/resume": { + "post": { + "operationId": "resumeCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Resume a campaign", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResumeCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:manage" + }, + "description": "**Required scope:** `campaigns:manage`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}/stop": { + "post": { + "operationId": "stopCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Stop a campaign", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StopCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:manage" + }, + "description": "**Required scope:** `campaigns:manage`" + } + }, + "/messaging/projects/{projectSlug}/campaigns/{id}/requeue": { + "post": { + "operationId": "requeueCampaign", + "tags": [ + "Campaigns" + ], + "summary": "Re-queue failed recipients", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "campaigns:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "projectSlug", + "in": "path" + }, + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequeueCampaignRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RequeueCampaignResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "402": { + "description": "This project has no number on a plan that includes Campaigns (`campaigns_not_entitled`)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "entitlement_required", + "message": "The account needs the required entitlement for this action.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#entitlement-required" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "campaigns:manage" + }, + "description": "**Required scope:** `campaigns:manage`" + } + }, + "/messaging/quicklinks": { + "post": { + "operationId": "createQuickLink", + "tags": [ + "QuickLink" + ], + "summary": "Create a QuickLink", + "description": "**Required scope:** `quicklink:manage`\n\nCreates a 15-minute hosted link that connects one WhatsApp number to a new session in the project.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "quicklink:manage", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateQuickLinkRequest" + } + } + } + }, + "responses": { + "201": { + "description": "QuickLink created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/QuickLinkResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "quicklink:manage" + } + } + }, + "/messaging/quicklinks/{id}": { + "get": { + "operationId": "getQuickLink", + "tags": [ + "QuickLink" + ], + "summary": "Read QuickLink status", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "quicklink:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Current QuickLink status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/QuickLinkStatusResponse" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "quicklink:manage" + }, + "description": "**Required scope:** `quicklink:manage`" + }, + "delete": { + "operationId": "cancelQuickLink", + "tags": [ + "QuickLink" + ], + "summary": "Cancel a QuickLink", + "description": "**Required scope:** `quicklink:manage`\n\nInvalidates the link and removes its pending session. Connected links cannot be cancelled.", + "security": [ + { + "BearerAuth": [] + } + ], + "x-required-scope": "quicklink:manage", + "parameters": [ + { + "schema": { + "type": "string" + }, + "required": true, + "name": "id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Cancelled", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "enum": [ + true + ] + }, + "message": { + "type": "string" + } + }, + "required": [ + "success", + "message" + ] + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "invalid_parameter", + "message": "Correct the invalid request field.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-parameter" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "authentication_error", + "code": "invalid_credential", + "message": "Supply a valid credential.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#invalid-credential" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "permission_error", + "code": "permission_denied", + "message": "The credential does not have access to this resource.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#permission-denied" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "invalid_request_error", + "code": "resource_not_found", + "message": "The resource is unavailable to this caller.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#resource-not-found" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicError" + }, + "example": { + "error": { + "type": "api_error", + "code": "internal_error", + "message": "An unexpected service failure occurred. Keep the request ID for support.", + "param": null + }, + "data": null, + "docs": "https://docs.polymorfa.com/api/errors#internal-error" + } + } + } + } + }, + "x-mint": { + "content": "quicklink:manage" + } + } + }, + "/quicklink/{token}": { + "get": { + "operationId": "getQuickLinkState", + "tags": [ + "QuickLink" + ], + "security": [], + "summary": "Read QuickLink state", + "description": "Returns the hosted page state for a QuickLink. Public; the token in the URL is the credential. Starts the session on first read.", + "parameters": [ + { + "schema": { + "type": "string", + "description": "Opaque QuickLink token from the hosted URL." + }, + "required": true, + "name": "token", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Current QuickLink state", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/QuickLinkState" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/quicklink/{token}/logo": { + "get": { + "operationId": "getQuickLinkLogo", + "tags": [ + "QuickLink" + ], + "security": [], + "summary": "Read the QuickLink page logo", + "description": "Returns the saved logo image for the page. Public; the token in the URL is the credential.", + "parameters": [ + { + "schema": { + "type": "string", + "description": "Opaque QuickLink token from the hosted URL." + }, + "required": true, + "name": "token", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Logo image", + "content": { + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/quicklink/{token}/code": { + "post": { + "operationId": "requestQuickLinkCode", + "tags": [ + "QuickLink" + ], + "security": [], + "summary": "Request a QuickLink pairing code", + "parameters": [ + { + "schema": { + "type": "string", + "description": "Opaque QuickLink token from the hosted URL." + }, + "required": true, + "name": "token", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/QuickLinkCodeRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Pairing code issued", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "phone": { + "type": "string" + } + }, + "required": [ + "code", + "phone" + ] + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/quicklink/{token}/confirm": { + "post": { + "operationId": "confirmQuickLink", + "tags": [ + "QuickLink" + ], + "security": [], + "summary": "Confirm a linked QuickLink", + "description": "Records consent, applies the chat-history choice, assigns Customer ownership when applicable, and returns the redirect target.", + "parameters": [ + { + "schema": { + "type": "string", + "description": "Opaque QuickLink token from the hosted URL." + }, + "required": true, + "name": "token", + "in": "path" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/QuickLinkConfirmRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Connected", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "connected" + ] + }, + "phone": { + "type": "string", + "nullable": true + }, + "historySync": { + "type": "boolean" + }, + "redirectUrl": { + "type": "string", + "nullable": true + } + }, + "required": [ + "status", + "phone", + "historySync", + "redirectUrl" + ] + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/quicklink/{token}/cancel": { + "post": { + "operationId": "cancelQuickLinkByToken", + "tags": [ + "QuickLink" + ], + "security": [], + "summary": "Cancel a QuickLink from the hosted page", + "parameters": [ + { + "schema": { + "type": "string", + "description": "Opaque QuickLink token from the hosted URL." + }, + "required": true, + "name": "token", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Cancelled", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "cancelled" + ] + }, + "redirectUrl": { + "type": "string", + "nullable": true + } + }, + "required": [ + "status", + "redirectUrl" + ] + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "description": "Bad request — request body or params failed validation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Missing or invalid authentication token", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Authenticated but not permitted (missing scope or rule violation)", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Resource not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + } + }, + "x-webhooks": { + "message.received": { + "post": { + "operationId": "onMessageReceived", + "summary": "Incoming message", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageReceivedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.sent": { + "post": { + "operationId": "onMessageSent", + "summary": "Outgoing message successfully sent", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageSentEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.ack": { + "post": { + "operationId": "onMessageAck", + "summary": "Delivery acknowledgement", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageAckEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.revoked": { + "post": { + "operationId": "onMessageRevoked", + "summary": "Message revoked", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageRevokedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.reaction": { + "post": { + "operationId": "onMessageReaction", + "summary": "Reaction added or removed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageReactionEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.edited": { + "post": { + "operationId": "onMessageEdited", + "summary": "Message edited", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageEditedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.update": { + "post": { + "operationId": "onMessageUpdate", + "summary": "Generic message update", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.delete": { + "post": { + "operationId": "onMessageDelete", + "summary": "Message deleted from another device", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageDeleteEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.vote": { + "post": { + "operationId": "onMessageVote", + "summary": "Poll vote cast", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageVoteEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "session.status": { + "post": { + "operationId": "onSessionStatus", + "summary": "Session status change", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionStatusEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "session.connected": { + "post": { + "operationId": "onSessionConnected", + "summary": "Session connected to WhatsApp", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionConnectedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "session.logged_out": { + "post": { + "operationId": "onSessionLoggedOut", + "summary": "Session logged out", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionLoggedOutEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "session.phone_offline": { + "post": { + "operationId": "onSessionPhoneOffline", + "summary": "Primary phone has been offline for an extended period", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionPhoneOfflineEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "group.update": { + "post": { + "operationId": "onGroupUpdate", + "summary": "Group metadata changed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "group.participant": { + "post": { + "operationId": "onGroupParticipant", + "summary": "Group participants added/removed/promoted/demoted", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GroupParticipantEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "presence.update": { + "post": { + "operationId": "onPresenceUpdate", + "summary": "User or chat presence change", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PresenceUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "contact.update": { + "post": { + "operationId": "onContactUpdate", + "summary": "Contact info changed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ContactUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "chat.archive": { + "post": { + "operationId": "onChatArchive", + "summary": "Chat archived or pinned", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatArchiveEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "chat.mute": { + "post": { + "operationId": "onChatMute", + "summary": "Chat muted or unmuted", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatMuteEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "chat.read": { + "post": { + "operationId": "onChatRead", + "summary": "Chat marked read or unread", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatReadEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "chat.clear": { + "post": { + "operationId": "onChatClear", + "summary": "Chat cleared", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatClearEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "chat.delete": { + "post": { + "operationId": "onChatDelete", + "summary": "Chat deleted", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChatDeleteEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.received": { + "post": { + "operationId": "onCallReceived", + "summary": "Incoming call", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallReceivedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.missed": { + "post": { + "operationId": "onCallMissed", + "summary": "Call missed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallMissedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.accepted": { + "post": { + "operationId": "onCallAccepted", + "summary": "Call accepted", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallAcceptedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.rejected": { + "post": { + "operationId": "onCallRejected", + "summary": "Call rejected", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallRejectedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.ended": { + "post": { + "operationId": "onCallEnded", + "summary": "Call ended", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallEndedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.telemetry": { + "post": { + "operationId": "onCallTelemetry", + "summary": "Call telemetry", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallTelemetryEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.participant_joined": { + "post": { + "operationId": "onCallParticipantJoined", + "summary": "Participant joined a call", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallParticipantJoinedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.participant_state": { + "post": { + "operationId": "onCallParticipantState", + "summary": "Participant call state changed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallParticipantStateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "call.participant_left": { + "post": { + "operationId": "onCallParticipantLeft", + "summary": "Participant left a call", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CallParticipantLeftEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "newsletter.update": { + "post": { + "operationId": "onNewsletterUpdate", + "summary": "Newsletter subscription change", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewsletterUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "blocklist.update": { + "post": { + "operationId": "onBlocklistUpdate", + "summary": "Blocklist changed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BlocklistUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "labels.update": { + "post": { + "operationId": "onLabelsUpdate", + "summary": "Label edited / associated / star toggled", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LabelsUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "business.quick_reply.update": { + "post": { + "operationId": "onBusinessQuickReplyUpdate", + "summary": "WhatsApp Business App quick reply changed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BusinessQuickReplyUpdateEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "history.sync": { + "post": { + "operationId": "onHistorySync", + "summary": "History sync chunk", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HistorySyncEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "command.result": { + "post": { + "operationId": "onCommandResult", + "summary": "Async command completed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CommandResultEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.enabled": { + "post": { + "operationId": "onCustomerEnabled", + "summary": "Customers enabled for a project", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerEnabledEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.created": { + "post": { + "operationId": "onCustomerCreated", + "summary": "Customer created", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerCreatedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.updated": { + "post": { + "operationId": "onCustomerUpdated", + "summary": "Customer updated", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerUpdatedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.archiving": { + "post": { + "operationId": "onCustomerArchiving", + "summary": "Customer archival started", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerArchivingEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.archived": { + "post": { + "operationId": "onCustomerArchived", + "summary": "Customer archived", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerArchivedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.restored": { + "post": { + "operationId": "onCustomerRestored", + "summary": "Customer restored", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRestoredEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.pairing_link.created": { + "post": { + "operationId": "onCustomerPairingLinkCreated", + "summary": "Customer pairing link created", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPairingLinkCreatedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.pairing_link.opened": { + "post": { + "operationId": "onCustomerPairingLinkOpened", + "summary": "Customer pairing link opened", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPairingLinkOpenedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.pairing_link.connected": { + "post": { + "operationId": "onCustomerPairingLinkConnected", + "summary": "Customer pairing link connected", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPairingLinkConnectedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.pairing_link.failed": { + "post": { + "operationId": "onCustomerPairingLinkFailed", + "summary": "Customer pairing attempt failed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPairingLinkFailedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.pairing_link.expired": { + "post": { + "operationId": "onCustomerPairingLinkExpired", + "summary": "Customer pairing link expired", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPairingLinkExpiredEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.pairing_link.revoked": { + "post": { + "operationId": "onCustomerPairingLinkRevoked", + "summary": "Customer pairing link revoked", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPairingLinkRevokedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.number.attached": { + "post": { + "operationId": "onCustomerNumberAttached", + "summary": "Number attached to a Customer", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerNumberAttachedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.number.transferred": { + "post": { + "operationId": "onCustomerNumberTransferred", + "summary": "Number transferred to a Customer", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerNumberTransferredEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "customer.number.disconnected": { + "post": { + "operationId": "onCustomerNumberDisconnected", + "summary": "Customer Number disconnected", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerNumberDisconnectedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "bansafe.enforcement": { + "post": { + "operationId": "onBansafeEnforcement", + "summary": "WhatsApp applied an enforcement to a number, or a ban was reported", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanSafeEnforcementEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "bansafe.action": { + "post": { + "operationId": "onBansafeAction", + "summary": "Polymorfa applied, changed, or lifted a safety restriction on a number", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanSafeActionEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "bansafe.health_threshold": { + "post": { + "operationId": "onBansafeHealthThreshold", + "summary": "A project's present Health rule crossed below its threshold", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanSafeHealthThresholdEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "bansafe.incident": { + "post": { + "operationId": "onBansafeIncident", + "summary": "A restriction was recorded on a number, or the record of one settled", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanSafeIncidentEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "bansafe.claim": { + "post": { + "operationId": "onBansafeClaim", + "summary": "A Ban Insurance claim was filed on a ban, decided, paid, or reversed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanSafeClaimEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "message.failed": { + "post": { + "operationId": "onMessageFailed", + "summary": "Outbound send failed, including a send refused by safety", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageFailedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "template.status": { + "post": { + "operationId": "onTemplateStatus", + "summary": "Message template approval status changed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateStatusEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.paused": { + "post": { + "operationId": "onCampaignPaused", + "summary": "Campaign paused", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignPausedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.completed": { + "post": { + "operationId": "onCampaignCompleted", + "summary": "Campaign finished sending", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignCompletedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.failed": { + "post": { + "operationId": "onCampaignFailed", + "summary": "Campaign failed", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignFailedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.recipient_sent": { + "post": { + "operationId": "onCampaignRecipientSent", + "summary": "A campaign recipient was sent", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignRecipientSentEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.recipient_failed": { + "post": { + "operationId": "onCampaignRecipientFailed", + "summary": "A campaign recipient failed after its last attempt", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignRecipientFailedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.recipient_skipped": { + "post": { + "operationId": "onCampaignRecipientSkipped", + "summary": "A campaign recipient was skipped", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignRecipientSkippedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.throttled": { + "post": { + "operationId": "onCampaignThrottled", + "summary": "Campaign sending was paced", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignThrottledEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.cap_reached": { + "post": { + "operationId": "onCampaignCapReached", + "summary": "A sending number reached its hourly or daily cap", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignCapReachedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + }, + "campaign.cold_blocked": { + "post": { + "operationId": "onCampaignColdBlocked", + "summary": "A campaign recipient was held because they never wrote first", + "tags": [ + "Webhooks" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignColdBlockedEvent" + } + } + } + }, + "responses": { + "2XX": { + "description": "Return any 2xx status to acknowledge receipt. Non-2xx responses are retried according to the retry policy." + } + } + } + } + } +} diff --git a/contracts/drafts/bansafe/openapi.platform.json b/contracts/drafts/bansafe/openapi.platform.json new file mode 100644 index 0000000..f40a6c1 --- /dev/null +++ b/contracts/drafts/bansafe/openapi.platform.json @@ -0,0 +1,27858 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Polymorfa Console & Management API", + "version": "1.0.0", + "description": "Complete console/management surface. Resource-oriented REST: `{param}` path variables, single-word action sub-resources.\n\nNamespaces decide inclusion:\n- `/platform/…` — **public registry** (138 endpoints): each endpoint declares either a scoped `pmfa_` organization key or a verified live dashboard JWT, or dashboard-only authorization when a specific user's authority is required. Only implemented handlers are published to customers and SDKs.\n- `/console/…` — **console-only** (64 endpoints): verified dashboard identity. EXCLUDED from the published spec; reason per endpoint.\n- `/admin/…` — **staff-only** (53 endpoints): Polymorfa internal staff. EXCLUDED.\n\nThe published customer spec = this document filtered to `x-audience: public` endpoints with an implemented runtime handler.\nMost transitional body/response schemas remain loose (`additionalProperties: true`); session-control operations use explicit strict schemas." + }, + "servers": [ + { + "url": "https://api.polymorfa.com" + }, + { + "url": "http://localhost:8080", + "description": "local dev" + } + ], + "paths": { + "/platform/sessions": { + "get": { + "operationId": "listPlatformSessions", + "tags": [ + "sessions" + ], + "summary": "List sessions", + "description": "Lists every session in the authenticated organization or selected project, including disconnected sessions and their latest status reason.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "x-merged-endpoints": [ + "listSessionsByOrganization" + ], + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PlatformSession" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/platform/sessions/{sessionId}/start": { + "post": { + "operationId": "startPlatformSession", + "tags": [ + "sessions" + ], + "summary": "Start a session", + "description": "Starts a stopped session or retries a session whose runtime failed. The identifier may be the session UUID or stable session slug.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "session", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionProjectContext" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionStartResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "500": { + "$ref": "#/components/responses/InternalError" + } + } + } + }, + "/platform/sessions/{sessionId}/stop": { + "post": { + "operationId": "stopPlatformSession", + "tags": [ + "sessions" + ], + "summary": "Stop a session", + "description": "Requests an asynchronous stop for one session. The identifier may be the session UUID or stable session slug.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "session", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionProjectContext" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionStopResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "500": { + "$ref": "#/components/responses/InternalError" + } + } + } + }, + "/platform/sessions/{sessionId}": { + "delete": { + "operationId": "deletePlatformSession", + "tags": [ + "sessions" + ], + "summary": "Remove a session", + "description": "Permanently removes one session and terminates its active connection when needed.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "session", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionRemoveResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "patch": { + "operationId": "setSessionTierOverride", + "tags": [ + "sessions" + ], + "summary": "Set a session tier override", + "description": "Sets an explicit session tier or clears the override with null.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "session", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionTierOverrideRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ManagedSession" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/sessions/stop": { + "post": { + "operationId": "stopSessions", + "tags": [ + "sessions" + ], + "summary": "Stop multiple sessions", + "description": "Requests asynchronous stops for up to 100 session UUIDs or slugs in the authenticated project scope.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionBatchRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionBatchStopResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "500": { + "$ref": "#/components/responses/InternalError" + } + } + } + }, + "/platform/sessions/delete": { + "post": { + "operationId": "deleteSessions", + "tags": [ + "sessions" + ], + "summary": "Remove multiple sessions", + "description": "Permanently removes up to 100 session UUIDs or slugs and terminates any rows that were still active.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SessionBatchRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionBatchRemoveResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/platform/sessions/testing": { + "post": { + "operationId": "createTestingSession", + "tags": [ + "sessions" + ], + "summary": "Create a testing number", + "description": "Creates a disconnected simulated session with testMode enabled. Team API keys require projectId in the body.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTestingNumberRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/TestingSessionId" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "500": { + "$ref": "#/components/responses/InternalError" + } + } + } + }, + "/platform/bans": { + "get": { + "operationId": "listSessionBans", + "tags": [ + "bans" + ], + "summary": "List session bans", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/bans/active": { + "get": { + "operationId": "listActiveSessionBans", + "tags": [ + "bans" + ], + "summary": "List active session bans", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/bansafe/health": { + "get": { + "operationId": "listBanSafeHealth", + "tags": [ + "bansafe" + ], + "summary": "List number safety", + "description": "Lists present Health, findings counts, and the active Polymorfa restriction for every number in one project. Health is a 0 to 100 estimate from rules v1 or a validated learned model. It remains null until enough fresh evidence is available.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeNumber" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/health/{session}": { + "get": { + "operationId": "getBanSafeHealth", + "tags": [ + "bansafe" + ], + "summary": "Get number safety", + "description": "Returns one number's present Health estimate and model metadata, retained open and acknowledged findings with their observation times, directly observed account state, the active Polymorfa restriction, and how that restriction lifts. Recorded findings and observed state remain separate from the estimate.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "session", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeNumberDetail" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/health/{session}/history": { + "get": { + "operationId": "listBanSafeHealthHistory", + "tags": [ + "bansafe" + ], + "summary": "List number health history", + "description": "Returns the newest Health evaluations since the requested date, up to the limit, ordered oldest to newest. Each point carries its estimator source and version, evidence coverage, reliability, and availability reason.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "session", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 720, + "default": 720 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeHealthHistory" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/signals": { + "get": { + "operationId": "listBanSafeSignals", + "tags": [ + "bansafe" + ], + "summary": "List BanSafe telemetry signals", + "description": "Lists the bounded numeric, boolean, enum, histogram, and error-code aggregate signals that BanSafe can return. The catalogue contains no message content, recipient identifiers, or raw telemetry records.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeSignalDefinition" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/telemetry/{session}": { + "get": { + "operationId": "getBanSafeTelemetry", + "tags": [ + "bansafe" + ], + "summary": "Get latest BanSafe telemetry", + "description": "Returns collection availability and the latest supported telemetry snapshot for one number. Empty collection is reported as not collected, not as a disabled collector.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "session", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeTelemetryDetail" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/telemetry/{session}/history": { + "get": { + "operationId": "listBanSafeTelemetryHistory", + "tags": [ + "bansafe" + ], + "summary": "List BanSafe telemetry history", + "description": "Returns the newest supported telemetry snapshots for one number. Signals are fixed-schema safe aggregates with explicit measured state; raw records and identifiers inside them are not returned.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "session", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "default": 10 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeTelemetrySnapshot" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/collection": { + "get": { + "operationId": "listBanSafeCollection", + "tags": [ + "bansafe" + ], + "summary": "List BanSafe collection status", + "description": "Lists telemetry collection freshness for the numbers in one project. Status is derived from ingested records and does not guess whether a collector flag is configured.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeCollectionSession" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/health-actions": { + "get": { + "operationId": "listBanSafeHealthActions", + "tags": [ + "bansafe" + ], + "summary": "List Health rule actions", + "description": "Lists the durable customer-visible outcomes of project Health rule actions, newest first. Internal leases, retry bookkeeping, runtime identifiers, and free-form outcomes are omitted.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "session", + "in": "query", + "required": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 256 + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "pending", + "running", + "succeeded", + "failed", + "cancelled" + ] + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeHealthAction" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/findings": { + "get": { + "operationId": "listBanSafeFindings", + "tags": [ + "bansafe" + ], + "summary": "List safety findings", + "description": "Lists safety findings across the organization, filterable by project, number, status, and severity. Evidence is numbers only and never contains message content or a recipient identifier.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "session", + "in": "query", + "required": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 256 + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "open", + "acknowledged", + "resolved" + ] + } + }, + { + "name": "severity", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "info", + "warning", + "critical" + ] + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeFinding" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/findings/{findingId}/acknowledge": { + "post": { + "operationId": "acknowledgeBanSafeFinding", + "tags": [ + "bansafe" + ], + "summary": "Acknowledge a safety finding", + "description": "Records that a named person on the team has seen this finding, optionally silences its notifications for up to 30 days, and unlocks the appeal form. It does not change the Health estimate, the restriction, or any campaign limit. Requires a signed-in organization owner, admin, or developer; an API key or token is refused with `bansafe_ack_requires_dashboard_identity`.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-dashboard-only": true, + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "findingId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AcknowledgeBanSafeFindingInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeFindingAcknowledgement" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/enforcement": { + "get": { + "operationId": "listBanSafeEnforcement", + "tags": [ + "bansafe" + ], + "summary": "List number restrictions", + "description": "Lists every number Polymorfa is currently restricting, what the restriction blocks, and the exact condition that lifts it.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "rung", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeEnforcementSummary" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/enforcement/{session}/appeal": { + "post": { + "operationId": "appealBanSafeEnforcement", + "tags": [ + "bansafe" + ], + "summary": "Appeal a number restriction", + "description": "Files one appeal against a number's restriction. Every open finding on the number must be acknowledged first, otherwise the request is refused with `findings_unacknowledged`. Filing an appeal does not change the restriction. Requires a signed-in organization owner, admin, or developer.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-dashboard-only": true, + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "session", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AppealBanSafeEnforcementInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeAppealReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/bansafe/incidents": { + "get": { + "operationId": "listBanSafeIncidents", + "tags": [ + "bansafe" + ], + "summary": "List safety incidents", + "description": "Lists the WhatsApp restrictions and customer reports recorded for the organization's numbers.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "session", + "in": "query", + "required": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 256 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeIncident" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "post": { + "operationId": "createBanSafeIncident", + "tags": [ + "bansafe" + ], + "summary": "Report a ban", + "description": "Records that WhatsApp restricted or banned one of your numbers. Send the same `Idempotency-Key` to retry safely for the same number; a repeat returns the original report. Reusing the key for a different number returns `409 bansafe_incident_idempotency_scope_conflict`.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportBanSafeIncidentInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeIncidentReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/bansafe/incidents/{incidentId}/retract": { + "post": { + "operationId": "retractBanSafeIncident", + "tags": [ + "bansafe" + ], + "summary": "Withdraw a ban report", + "description": "Withdraws a customer report and returns its incident record. Repeating the request returns the closed record. An incident observed from WhatsApp cannot be withdrawn and returns `409 bansafe_incident_not_a_report`. An unknown incident returns 404.\n\nRequires a team API key with `sessions:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeIncident" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/bansafe/claims": { + "get": { + "operationId": "listBanSafeClaims", + "tags": [ + "bansafe" + ], + "summary": "List Ban Insurance claims", + "description": "Lists the Ban Insurance claims filed on your numbers, newest first. A claim is filed automatically when a ban is recorded on a number whose plan includes insurance; there is no request to file one.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "session", + "in": "query", + "required": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 256 + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "filed", + "under_review", + "approved", + "denied", + "paid", + "reversed" + ] + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeClaim" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/bansafe/claims/{claimId}": { + "get": { + "operationId": "getBanSafeClaim", + "tags": [ + "bansafe" + ], + "summary": "Get a Ban Insurance claim", + "description": "Returns one claim: the 30 days it covers, the credits that number consumed in them, the most the plan returns, what the claim returns, what the ban was attributed to, and the evidence counts behind that.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "claimId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/BanSafeClaim" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/safe-mode": { + "get": { + "operationId": "getProjectSafeModeCeiling", + "tags": [ + "bansafe" + ], + "summary": "Get a project's Safe Mode ceiling", + "description": "Returns the most visible sending behaviour any number in this project may use. Every setting is off by default. `entitled` reports whether the plan includes BanSafe Lite, which Safe Mode is part of, and `entitlementReason` gives the reason a raise would be refused.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectSafeMode" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "put": { + "operationId": "updateProjectSafeModeCeiling", + "tags": [ + "bansafe" + ], + "summary": "Set a project's Safe Mode ceiling", + "description": "Sets the most visible behaviour any number in this project may use. Send only the settings you want to change. Presence and read receipts are visible to the people these numbers message: turning them on makes a number appear online, exposes last seen subject to the account's privacy settings, and puts blue ticks on incoming messages. Raising a setting requires a plan that includes BanSafe Lite, and lowering one is always allowed. A signed-in caller must be an organization owner, admin, or developer.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectSafeModeInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectSafeMode" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "402": { + "$ref": "#/components/responses/PaymentRequired" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/PropagationPending" + } + } + } + }, + "/platform/sessions/{sessionId}/safe-mode": { + "get": { + "operationId": "getNumberSafeMode", + "tags": [ + "bansafe" + ], + "summary": "Get a number's Safe Mode", + "description": "Returns the project ceiling, this number's override, the policy in force, and what the number last reported it is running. `mismatch` is true when the two differ. `entitled` reports whether the plan includes BanSafe Lite, which Safe Mode is part of, and `entitlementReason` gives the reason a raise would be refused.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "session", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionSafeMode" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "put": { + "operationId": "updateNumberSafeMode", + "tags": [ + "bansafe" + ], + "summary": "Set a number's Safe Mode", + "description": "Sets one number's Safe Mode. Each setting accepts `inherit` to follow the project ceiling. An override may only be equally or more conservative than the ceiling; a more visible value is refused with `safe_mode_exceeds_project_ceiling`. Raising a setting requires a plan that includes BanSafe Lite, and lowering one is always allowed. A signed-in caller must be an organization owner, admin, or developer.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "session", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSessionSafeModeInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/SessionSafeMode" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "402": { + "$ref": "#/components/responses/PaymentRequired" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/PropagationPending" + } + } + } + }, + "/platform/projects/{projectId}/warmup-plan": { + "get": { + "operationId": "getProjectWarmupPlanSettings", + "tags": [ + "bansafe" + ], + "summary": "Get a project's warm-up plan", + "description": "Returns whether numbers in this project have a daily allowance, the two settings that shape the ramp, the per-number daily cap it climbs to, and the projected allowance day by day. `entitled` reports whether the plan includes BanSafe Lite, which the warm-up plan is part of.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWarmupPlan" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "put": { + "operationId": "updateProjectWarmupPlanSettings", + "tags": [ + "bansafe" + ], + "summary": "Set a project's warm-up plan", + "description": "Turns the warm-up plan on or off for a project and sets how long the ramp takes and how many messages a number may send on its first day. Send only the settings you want to change. While the plan is on, a send past a number's allowance is refused with `bansafe_daily_allowance_reached` and campaign recipients are deferred to the next reset. Turning the plan on requires a plan that includes BanSafe Lite; turning it off is always allowed. A signed-in caller must be an organization owner, admin, or developer.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectWarmupPlanInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWarmupPlan" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "402": { + "$ref": "#/components/responses/PaymentRequired" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/PropagationPending" + } + } + } + }, + "/platform/projects/{projectId}/health-policy": { + "get": { + "operationId": "getProjectHealthPolicySettings", + "tags": [ + "bansafe" + ], + "summary": "Get a project's health policy", + "description": "Returns the health threshold and the actions configured for numbers in this project. Integration flags report whether email and webhook delivery are ready to use.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectHealthPolicy" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "put": { + "operationId": "updateProjectHealthPolicySettings", + "tags": [ + "bansafe" + ], + "summary": "Set a project's health policy", + "description": "Replaces the project policy when the supplied version matches the stored version. The rule applies only when an available health estimate is below the threshold; an unavailable estimate triggers no action. Stopping disconnects a session and retains its linked credentials. Logging out requires relinking.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectHealthPolicyInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectHealthPolicy" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/insurance-evidence": { + "get": { + "operationId": "getInsuranceEvidenceSettings", + "tags": [ + "bansafe" + ], + "summary": "Get a project's insurance evidence setting", + "description": "Returns whether evidence collection about other linked devices is enabled and whether any number in the project has Ban Insurance included in its plan. Collection is off until explicitly enabled.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectInsuranceEvidence" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "put": { + "operationId": "updateInsuranceEvidenceSettings", + "tags": [ + "bansafe" + ], + "summary": "Set a project's insurance evidence setting", + "description": "Enables or disables collection of counts about other linked devices. Collection never includes messages, recipient identities, or device names. Disabling collection discards stored device evidence. A 503 `propagation_pending` means the setting was stored but a connected number has not confirmed it; retry the request. A signed-in caller must be an organization owner, admin, or developer.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectInsuranceEvidenceInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectInsuranceEvidence" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "503": { + "$ref": "#/components/responses/PropagationPending" + } + } + } + }, + "/platform/campaigns": { + "get": { + "operationId": "listPlatformCampaigns", + "tags": [ + "campaigns" + ], + "summary": "List platform campaigns", + "description": "Public Management API. Requires `campaigns:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "projectSlug", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "post": { + "operationId": "createPlatformCampaign", + "tags": [ + "campaigns" + ], + "summary": "Create campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}": { + "get": { + "operationId": "getPlatformCampaign", + "tags": [ + "campaigns" + ], + "summary": "Get campaign", + "description": "Public Management API. Requires `campaigns:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "patch": { + "operationId": "updateCampaign", + "tags": [ + "campaigns" + ], + "summary": "Update campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "deleteCampaign", + "tags": [ + "campaigns" + ], + "summary": "Delete campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/launch": { + "post": { + "operationId": "launchPlatformCampaign", + "tags": [ + "campaigns" + ], + "summary": "Launch campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/pause": { + "post": { + "operationId": "pausePlatformCampaign", + "tags": [ + "campaigns" + ], + "summary": "Pause campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/resume": { + "post": { + "operationId": "resumePlatformCampaign", + "tags": [ + "campaigns" + ], + "summary": "Resume campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/stop": { + "post": { + "operationId": "stopPlatformCampaign", + "tags": [ + "campaigns" + ], + "summary": "Stop campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/archive": { + "post": { + "operationId": "archiveCampaign", + "tags": [ + "campaigns" + ], + "summary": "Archive campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/duplicate": { + "post": { + "operationId": "duplicateCampaign", + "tags": [ + "campaigns" + ], + "summary": "Duplicate campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/requeue": { + "post": { + "operationId": "requeueFailedCampaign", + "tags": [ + "campaigns" + ], + "summary": "Requeue failed campaign", + "description": "Public Management API. Requires `campaigns:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/analytics": { + "get": { + "operationId": "getPlatformCampaignAnalytics", + "tags": [ + "campaigns" + ], + "summary": "Get campaign analytics", + "description": "Public Management API. Requires `campaigns:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/events": { + "get": { + "operationId": "listCampaignEvents", + "tags": [ + "campaigns" + ], + "summary": "List campaign events", + "description": "Public Management API. Requires `campaigns:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/campaigns/{campaignId}/recipients": { + "get": { + "operationId": "listCampaignRecipients", + "tags": [ + "campaigns" + ], + "summary": "List campaign recipients", + "description": "Public Management API. Requires `campaigns:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/audiences": { + "get": { + "operationId": "listAudiences", + "tags": [ + "audiences" + ], + "summary": "List audiences", + "description": "Public Management API. Requires a team API key with `campaigns:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "post": { + "operationId": "createAudience", + "tags": [ + "audiences" + ], + "summary": "Create audience", + "description": "Public Management API. Requires a team API key with `campaigns:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/audiences/{listId}": { + "get": { + "operationId": "getAudience", + "tags": [ + "audiences" + ], + "summary": "Get audience", + "description": "Public Management API. Requires a team API key with `campaigns:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "listId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "deleteAudience", + "tags": [ + "audiences" + ], + "summary": "Delete audience", + "description": "Public Management API. Requires a team API key with `campaigns:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "listId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/audiences/uploads": { + "post": { + "operationId": "createAudienceUploadUrl", + "tags": [ + "audiences" + ], + "summary": "Create audience upload url", + "description": "Public Management API. Requires a team API key with `campaigns:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/templates": { + "get": { + "operationId": "listMessageTemplates", + "tags": [ + "templates" + ], + "summary": "List message templates", + "description": "Lists the message-template drafts in one project.\n\nRequires `templates:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "templates:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "maxItems": 500, + "items": { + "$ref": "#/components/schemas/ManagementTemplate" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "post": { + "operationId": "createMessageTemplate", + "tags": [ + "templates" + ], + "summary": "Create a message-template draft", + "description": "Creates an incomplete or complete message-template draft in one project.\n\nRequires `templates:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "templates:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateManagementTemplateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/TemplateId" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/templates/{templateId}": { + "get": { + "operationId": "getMessageTemplate", + "tags": [ + "templates" + ], + "summary": "Get a message-template draft", + "description": "Gets one message-template draft from the specified project.\n\nRequires `templates:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "templates:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "templateId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/ManagementTemplate" + } + ], + "nullable": true + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "patch": { + "operationId": "updateMessageTemplate", + "tags": [ + "templates" + ], + "summary": "Update a message-template draft", + "description": "Updates one message-template draft in the project supplied in the request body.\n\nRequires `templates:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "templates:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "templateId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateManagementTemplateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ManagementTemplate" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "operationId": "deleteMessageTemplate", + "tags": [ + "templates" + ], + "summary": "Delete a message-template draft", + "description": "Deletes one message-template draft from the specified project.\n\nRequires `templates:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "templates:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "templateId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/DeleteManagementTemplateResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/flows": { + "get": { + "operationId": "listFlows", + "tags": [ + "flows" + ], + "summary": "List Flow drafts", + "description": "Lists compact WhatsApp Flow draft summaries in one project.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "maxItems": 250, + "items": { + "$ref": "#/components/schemas/FlowSummary" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "post": { + "operationId": "createFlow", + "tags": [ + "flows" + ], + "summary": "Create a Flow draft", + "description": "Creates a project-scoped WhatsApp Flow draft. A supplied draftId makes retries idempotent.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateFlowRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/FlowDraft" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/flows/{flowId}": { + "get": { + "operationId": "getFlow", + "tags": [ + "flows" + ], + "summary": "Get a Flow draft", + "description": "Gets one project-scoped WhatsApp Flow draft.\n\nRequires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "flowId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/FlowDraft" + } + ], + "nullable": true + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "patch": { + "operationId": "updateFlow", + "tags": [ + "flows" + ], + "summary": "Update a Flow draft", + "description": "Updates a Flow draft when expectedUpdatedAt matches the stored revision.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "flowId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateFlowRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/FlowDraft" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + }, + "delete": { + "operationId": "deleteFlow", + "tags": [ + "flows" + ], + "summary": "Delete a Flow draft", + "description": "Deletes a local Flow draft without deleting linked Meta Flow assets.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "flowId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/DeleteFlowResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/optouts": { + "get": { + "operationId": "listOptOuts", + "tags": [ + "optouts" + ], + "summary": "List opt outs", + "description": "Public Management API. Requires a team API key with `campaigns:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "post": { + "operationId": "createOptOut", + "tags": [ + "optouts" + ], + "summary": "Create opt out", + "description": "Public Management API. Requires a team API key with `campaigns:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/optouts/batch": { + "post": { + "operationId": "createOptOuts", + "tags": [ + "optouts" + ], + "summary": "Create opt outs", + "description": "Public Management API. Requires a team API key with `campaigns:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/optouts/{phone}": { + "delete": { + "operationId": "deleteOptOut", + "tags": [ + "optouts" + ], + "summary": "Delete opt out", + "description": "Public Management API. Requires a team API key with `campaigns:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "campaigns:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "phone", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/billing": { + "get": { + "operationId": "getBilling", + "tags": [ + "billing" + ], + "summary": "Get billing", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/billing/usage": { + "get": { + "operationId": "listUsageMeters", + "tags": [ + "billing" + ], + "summary": "List usage meters", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/billing/transactions": { + "get": { + "operationId": "listBillingTransactions", + "tags": [ + "billing" + ], + "summary": "List billing transactions", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/billing/pricing": { + "get": { + "operationId": "listTierPricing", + "tags": [ + "billing" + ], + "summary": "List tier pricing", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/billing/reminders": { + "patch": { + "operationId": "updateBillingReminderSettings", + "tags": [ + "billing" + ], + "summary": "Update billing reminder settings", + "description": "Public Management API. Requires a team API key with `sessions:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/team": { + "get": { + "operationId": "getOrganization", + "tags": [ + "team" + ], + "summary": "Get organization", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/organization": { + "patch": { + "operationId": "updateOrganization", + "tags": [ + "organization" + ], + "summary": "Update organization", + "description": "**EXCLUDED from the public API** (`console`). Organization changes require an authenticated console member.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Organization changes require an authenticated console member.", + "x-dashboard-only": true, + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/projects": { + "get": { + "operationId": "listProjects", + "tags": [ + "projects" + ], + "summary": "List projects", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "post": { + "operationId": "createProject", + "tags": [ + "projects" + ], + "summary": "Create project", + "description": "Public Management API. Requires a team API key with `sessions:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/projects/{projectId}": { + "patch": { + "operationId": "updateProject", + "tags": [ + "projects" + ], + "summary": "Update project settings", + "description": "Updates the display name, icon, or default number plan without changing the project ID, URL, stage, or individual number overrides.\n\nRequires a verified dashboard bearer and current organization authorization. The signed-in member must be an organization owner or admin. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard project name, icon, and default number plan settings. Requires a current owner or admin.", + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 200 + }, + "defaultTier": { + "type": "string", + "enum": [ + "free", + "standard", + "pro" + ] + }, + "icon": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "emoji", + "icon", + "image" + ] + }, + "value": { + "type": "string", + "minLength": 1, + "maxLength": 512 + }, + "color": { + "type": "string", + "maxLength": 64 + }, + "storageId": { + "type": "string", + "maxLength": 256 + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "object", + "additionalProperties": false, + "required": [ + "saved" + ], + "properties": { + "saved": { + "type": "boolean", + "enum": [ + true + ] + } + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/promote": { + "post": { + "operationId": "requestProductionEnrollment", + "tags": [ + "projects" + ], + "summary": "Request production enrollment", + "description": "Creates a durable production-enrollment operation. The project stays in development until provisioning succeeds. Poll the returned operationId for progress.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProductionEnrollmentRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProductionEnrollmentResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/customers/status": { + "get": { + "operationId": "getCustomersStatus", + "tags": [ + "customers" + ], + "summary": "Get Customers status", + "description": "Returns whether Customers is enabled for the exact project and its protected default Customer when enabled.\n\nRequires `customers:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/CustomersStatus" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/customers/enable": { + "post": { + "operationId": "enableCustomers", + "tags": [ + "customers" + ], + "summary": "Enable Customers", + "description": "Enables Customers once, creates the default Customer, and assigns every existing Number in the project to it atomically.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/CustomersEnablement" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/production-enrollments/{operationId}/approve": { + "post": { + "operationId": "approveProductionEnrollment", + "tags": [ + "projects" + ], + "summary": "Approve production enrollment", + "description": "Resumes a production-enrollment operation that requires approval.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProductionEnrollmentCommandResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/production-enrollments/{operationId}/cancel": { + "post": { + "operationId": "cancelProductionEnrollment", + "tags": [ + "projects" + ], + "summary": "Cancel production enrollment", + "description": "Requests cancellation of an active production-enrollment operation. Provisioned resources are compensated before cancellation completes.\n\nRequires `sessions:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProductionEnrollmentCommandResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/webhooks": { + "get": { + "operationId": "listOrganizationWebhooks", + "tags": [ + "webhooks" + ], + "summary": "List organization webhooks", + "description": "Lists only organization-owned webhook endpoints. Project-owned endpoints are excluded.\n\nRequires a team API key with `webhooks:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "eventType", + "in": "query", + "required": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + { + "name": "enabled", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationWebhook" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + }, + "post": { + "operationId": "createOrganizationWebhook", + "tags": [ + "webhooks" + ], + "summary": "Create an organization webhook", + "description": "Creates an organization-owned webhook and returns its generated signing secret once.\n\nRequires a team API key with `webhooks:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateOrganizationWebhookInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookCreationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/webhooks/{webhookId}": { + "get": { + "operationId": "getOrganizationWebhook", + "tags": [ + "webhooks" + ], + "summary": "Get an organization webhook", + "description": "Returns one organization-owned webhook without secret values.\n\nRequires a team API key with `webhooks:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhook" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "patch": { + "operationId": "updateOrganizationWebhook", + "tags": [ + "webhooks" + ], + "summary": "Update an organization webhook", + "description": "Updates settings without rotating the signing secret.\n\nRequires a team API key with `webhooks:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateOrganizationWebhookInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookMutationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + }, + "delete": { + "operationId": "deleteOrganizationWebhook", + "tags": [ + "webhooks" + ], + "summary": "Delete an organization webhook", + "description": "Deletes one organization-owned webhook.\n\nRequires a team API key with `webhooks:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookDeletionReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/webhooks/{webhookId}/secret-rotations": { + "post": { + "operationId": "rotateOrganizationWebhookSecret", + "tags": [ + "webhooks" + ], + "summary": "Rotate an organization webhook secret", + "description": "Rotates the signing secret and returns the new secret once.\n\nRequires a team API key with `webhooks:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RotateWebhookSecretInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookSecretRotationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/webhooks/{webhookId}/tests": { + "post": { + "operationId": "testOrganizationWebhook", + "tags": [ + "webhooks" + ], + "summary": "Send an organization webhook test", + "description": "Creates a synthetic organization event and a traceable webhook delivery.\n\nRequires a team API key with `webhooks:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestWebhookInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookTestReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/webhooks": { + "get": { + "operationId": "listProjectWebhooks", + "tags": [ + "webhooks" + ], + "summary": "List project webhooks", + "description": "Lists webhooks owned by the exact project in the route.\n\nRequires `webhooks:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "eventType", + "in": "query", + "required": false, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + { + "name": "enabled", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectWebhook" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "post": { + "operationId": "createProjectWebhook", + "tags": [ + "webhooks" + ], + "summary": "Create a project webhook", + "description": "Creates a project-owned webhook and returns its generated signing secret once.\n\nRequires `webhooks:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateProjectWebhookInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookCreationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/webhooks/{webhookId}": { + "get": { + "operationId": "getProjectWebhook", + "tags": [ + "webhooks" + ], + "summary": "Get a project webhook", + "description": "Returns one webhook owned by the exact project without secret values.\n\nRequires `webhooks:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhook" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "patch": { + "operationId": "updateProjectWebhook", + "tags": [ + "webhooks" + ], + "summary": "Update a project webhook", + "description": "Updates settings without rotating the signing secret.\n\nRequires `webhooks:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateProjectWebhookInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookMutationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + }, + "delete": { + "operationId": "deleteProjectWebhook", + "tags": [ + "webhooks" + ], + "summary": "Delete a project webhook", + "description": "Deletes one webhook owned by the exact project.\n\nRequires `webhooks:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookDeletionReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/webhooks/{webhookId}/secret-rotations": { + "post": { + "operationId": "rotateProjectWebhookSecret", + "tags": [ + "webhooks" + ], + "summary": "Rotate a project webhook secret", + "description": "Rotates the signing secret and returns the new secret once.\n\nRequires `webhooks:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RotateWebhookSecretInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookSecretRotationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/projects/{projectId}/webhooks/{webhookId}/tests": { + "post": { + "operationId": "testProjectWebhook", + "tags": [ + "webhooks" + ], + "summary": "Send a project webhook test", + "description": "Creates a synthetic project event and a traceable webhook delivery. An optional complete native envelope is accepted only with an exact HMS-enabled project session.\n\nRequires `webhooks:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhooks:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestWebhookInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookTestReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + } + }, + "/platform/events": { + "get": { + "operationId": "listOrganizationEvents", + "tags": [ + "events" + ], + "summary": "List organization events", + "description": "Lists organization-owned event metadata. Project-owned events are excluded.\n\nRequires a team API key with `events:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "events:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "type", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationEvent" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/platform/events/{eventId}": { + "get": { + "operationId": "getOrganizationEvent", + "tags": [ + "events" + ], + "summary": "Get an organization event", + "description": "Returns one organization-owned event and includes exact payload bytes only when requested and available.\n\nRequires a team API key with `events:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "events:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "eventId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "includePayload", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationEvent" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/events/{eventId}/replays": { + "post": { + "operationId": "replayOrganizationEvent", + "tags": [ + "events" + ], + "summary": "Replay an organization event", + "description": "Creates a new logical delivery for a retained organization event.\n\nRequires a team API key with `events:replay`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "events:replay", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "eventId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayEventInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationEventReplayReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + } + }, + "/platform/projects/{projectId}/events": { + "get": { + "operationId": "listProjectEvents", + "tags": [ + "events" + ], + "summary": "List project events", + "description": "Lists event metadata owned by the exact project in the route.\n\nRequires `events:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "events:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "type", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectEvent" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/events/{eventId}": { + "get": { + "operationId": "getProjectEvent", + "tags": [ + "events" + ], + "summary": "Get a project event", + "description": "Returns one event owned by the exact project and includes exact payload bytes only when requested and available.\n\nRequires `events:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "events:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "eventId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "includePayload", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectEvent" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/events/{eventId}/replays": { + "post": { + "operationId": "replayProjectEvent", + "tags": [ + "events" + ], + "summary": "Replay a project event", + "description": "Creates a new logical delivery for a retained event owned by the exact project.\n\nRequires `events:replay`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "events:replay", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "eventId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayEventInput" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectEventReplayReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + } + }, + "/platform/webhook-deliveries": { + "get": { + "operationId": "listOrganizationWebhookDeliveries", + "tags": [ + "webhook deliveries" + ], + "summary": "List organization webhook deliveries", + "description": "Lists logical deliveries for organization-owned webhooks. Project-owned deliveries are excluded.\n\nRequires a team API key with `webhook-deliveries:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "eventId", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "pending", + "delivering", + "retrying", + "succeeded", + "failed" + ] + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationWebhookDelivery" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/platform/webhook-deliveries/{deliveryId}": { + "get": { + "operationId": "getOrganizationWebhookDelivery", + "tags": [ + "webhook deliveries" + ], + "summary": "Get an organization webhook delivery", + "description": "Returns one logical organization webhook delivery.\n\nRequires a team API key with `webhook-deliveries:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookDelivery" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/webhook-deliveries/{deliveryId}/retry": { + "post": { + "operationId": "retryOrganizationWebhookDelivery", + "tags": [ + "webhook deliveries" + ], + "summary": "Retry an organization webhook delivery", + "description": "Appends a new immutable attempt to the same logical delivery.\n\nRequires a team API key with `webhook-deliveries:retry`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:retry", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookDeliveryRetryReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + } + }, + "/platform/webhook-deliveries/{deliveryId}/attempts": { + "get": { + "operationId": "listOrganizationWebhookDeliveryAttempts", + "tags": [ + "webhook deliveries" + ], + "summary": "List organization delivery attempts", + "description": "Lists immutable network attempts for one organization webhook delivery.\n\nRequires a team API key with `webhook-deliveries:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationWebhookDeliveryAttempt" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/webhook-deliveries/{deliveryId}/attempts/{attemptId}": { + "get": { + "operationId": "getOrganizationWebhookDeliveryAttempt", + "tags": [ + "webhook deliveries" + ], + "summary": "Get organization delivery attempt", + "description": "Returns one immutable network attempt.\n\nRequires a team API key with `webhook-deliveries:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "attemptId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationWebhookDeliveryAttempt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/webhook-deliveries": { + "get": { + "operationId": "listProjectWebhookDeliveries", + "tags": [ + "webhook deliveries" + ], + "summary": "List project webhook deliveries", + "description": "Lists logical webhook deliveries owned by the exact project in the route.\n\nRequires `webhook-deliveries:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "webhookId", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "eventId", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "pending", + "delivering", + "retrying", + "succeeded", + "failed" + ] + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectWebhookDelivery" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/webhook-deliveries/{deliveryId}": { + "get": { + "operationId": "getProjectWebhookDelivery", + "tags": [ + "webhook deliveries" + ], + "summary": "Get a project webhook delivery", + "description": "Returns one logical webhook delivery owned by the exact project.\n\nRequires `webhook-deliveries:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookDelivery" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/webhook-deliveries/{deliveryId}/retry": { + "post": { + "operationId": "retryProjectWebhookDelivery", + "tags": [ + "webhook deliveries" + ], + "summary": "Retry a project webhook delivery", + "description": "Appends a new immutable attempt to the same logical delivery owned by the exact project.\n\nRequires `webhook-deliveries:retry`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:retry", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookDeliveryRetryReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + }, + "422": { + "$ref": "#/components/responses/Unprocessable" + } + } + } + }, + "/platform/projects/{projectId}/webhook-deliveries/{deliveryId}/attempts": { + "get": { + "operationId": "listProjectWebhookDeliveryAttempts", + "tags": [ + "webhook deliveries" + ], + "summary": "List project webhook delivery attempts", + "description": "Lists immutable network attempts for one project webhook delivery.\n\nRequires `webhook-deliveries:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectWebhookDeliveryAttempt" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/projects/{projectId}/webhook-deliveries/{deliveryId}/attempts/{attemptId}": { + "get": { + "operationId": "getProjectWebhookDeliveryAttempt", + "tags": [ + "webhook deliveries" + ], + "summary": "Get a project webhook delivery attempt", + "description": "Returns one immutable network attempt owned by the exact project.\n\nRequires `webhook-deliveries:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "webhook-deliveries:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "deliveryId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "attemptId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectWebhookDeliveryAttempt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/operations": { + "get": { + "operationId": "listOrganizationOperations", + "tags": [ + "operations" + ], + "summary": "List organization operations", + "description": "Lists only organization-owned asynchronous operations. Project-owned operations are excluded.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "pending", + "running", + "action_required", + "cancelling", + "succeeded", + "failed", + "cancelled" + ] + } + }, + { + "name": "kind", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "auth_projection_repair", + "session_lifecycle", + "auth_session_purge", + "label_projection_purge", + "billing_reconciliation", + "auto_top_up", + "campaign", + "production_enrollment", + "retention_sweep", + "webhook_redrive" + ] + } + }, + { + "name": "resourceType", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "resourceId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OrganizationOperation" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/console/operations/{operationId}": { + "get": { + "operationId": "getOrganizationOperation", + "tags": [ + "operations" + ], + "summary": "Get an organization operation", + "description": "Returns one organization-owned asynchronous operation.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationOperation" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/operations/{operationId}/transitions": { + "get": { + "operationId": "listOrganizationOperationTransitions", + "tags": [ + "operations" + ], + "summary": "List organization operation transitions", + "description": "Lists immutable transitions for one organization-owned operation in ascending sequence.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "afterSequence", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int64", + "minimum": 0 + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OperationTransition" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/operations/{operationId}/cancel": { + "post": { + "operationId": "cancelOrganizationOperation", + "tags": [ + "operations" + ], + "summary": "Cancel an organization operation", + "description": "Requests cancellation after transactionally rechecking that the operation is cancellable.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/OrganizationOperationCancellationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/OperationCancellationConflict" + } + } + } + }, + "/console/projects/{projectId}/operations": { + "get": { + "operationId": "listProjectOperations", + "tags": [ + "operations" + ], + "summary": "List project operations", + "description": "Lists asynchronous operations owned by the exact project in the route.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "pending", + "running", + "action_required", + "cancelling", + "succeeded", + "failed", + "cancelled" + ] + } + }, + { + "name": "kind", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "auth_projection_repair", + "session_lifecycle", + "auth_session_purge", + "label_projection_purge", + "billing_reconciliation", + "auto_top_up", + "campaign", + "production_enrollment", + "retention_sweep", + "webhook_redrive" + ] + } + }, + { + "name": "resourceType", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "resourceId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "since", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "until", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ProjectOperation" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/projects/{projectId}/operations/{operationId}": { + "get": { + "operationId": "getProjectOperation", + "tags": [ + "operations" + ], + "summary": "Get a project operation", + "description": "Returns one asynchronous operation owned by the exact project in the route.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectOperation" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/projects/{projectId}/operations/{operationId}/transitions": { + "get": { + "operationId": "listProjectOperationTransitions", + "tags": [ + "operations" + ], + "summary": "List project operation transitions", + "description": "Lists immutable transitions for one project-owned operation in ascending sequence.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "afterSequence", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "format": "int64", + "minimum": 0 + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OperationTransition" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/projects/{projectId}/operations/{operationId}/cancel": { + "post": { + "operationId": "cancelProjectOperation", + "tags": [ + "operations" + ], + "summary": "Cancel a project operation", + "description": "Requests cancellation for an operation in the exact project after transactionally rechecking that it is cancellable.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard operation bookkeeping; unavailable to machine credentials.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "operationId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ProjectOperationCancellationReceipt" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/OperationCancellationConflict" + } + } + } + }, + "/platform/customers": { + "get": { + "operationId": "listCustomers", + "tags": [ + "customers" + ], + "summary": "List Customers", + "description": "Lists masked Customer summaries in the exact authenticated project with cursor pagination and filters.\n\nRequires `customers:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "cursor", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + }, + { + "name": "search", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "active", + "archiving", + "archived", + "all" + ] + } + }, + { + "name": "isDefault", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "hasNumbers", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "needsAttention", + "in": "query", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerSummary" + } + }, + "page": { + "$ref": "#/components/schemas/CursorPageMetadata" + } + }, + "required": [ + "data", + "page" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "post": { + "operationId": "createCustomer", + "tags": [ + "customers" + ], + "summary": "Create a Customer", + "description": "Creates a Customer with optional name, phone, and caller-defined external identifier.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCustomerRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/Customer" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/customers/{customerId}": { + "get": { + "operationId": "getCustomer", + "tags": [ + "customers" + ], + "summary": "Get a Customer", + "description": "Returns one Customer from the exact authenticated project.\n\nRequires `customers:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/Customer" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "patch": { + "operationId": "updateCustomer", + "tags": [ + "customers" + ], + "summary": "Update a Customer", + "description": "Updates supplied Customer profile fields. Null clears an optional field.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateCustomerRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/Customer" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/customers/{customerId}/archive": { + "post": { + "operationId": "archiveCustomer", + "tags": [ + "customers" + ], + "summary": "Archive a Customer", + "description": "Archives a non-default Customer. The default Customer cannot be archived.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerProjectRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/Customer" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/customers/{customerId}/restore": { + "post": { + "operationId": "restoreCustomer", + "tags": [ + "customers" + ], + "summary": "Restore a Customer", + "description": "Restores an archived Customer.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerProjectRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/Customer" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/customers/{customerId}/numbers": { + "get": { + "operationId": "listCustomerNumbers", + "tags": [ + "customers" + ], + "summary": "List Customer Numbers", + "description": "Lists Numbers assigned to one Customer in the exact project.\n\nRequires `customers:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerNumber" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/customers/{customerId}/events": { + "get": { + "operationId": "listCustomerEvents", + "tags": [ + "customers" + ], + "summary": "List recent Customer events", + "description": "Lists the newest Customer lifecycle events with safe metadata. Actor identities, message content, phone values, invitation tokens, and URLs are excluded.\n\nRequires `customers:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerEvent" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/customers/{customerId}/pairing-links": { + "post": { + "operationId": "createCustomerPairingLink", + "tags": [ + "customers" + ], + "summary": "Create a Customer pairing link", + "description": "Creates a revocable Customer invitation. The raw URL is returned only in this response.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCustomerPairingLinkRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/CreatedCustomerPairingLink" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + }, + "get": { + "operationId": "listCustomerPairingLinks", + "tags": [ + "customers" + ], + "summary": "List Customer pairing links", + "description": "Lists safe pairing-link metadata. Raw invitation tokens and URLs are never returned.\n\nRequires `customers:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerPairingLink" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/platform/customers/{customerId}/pairing-links/{pairingLinkId}": { + "delete": { + "operationId": "revokeCustomerPairingLink", + "tags": [ + "customers" + ], + "summary": "Revoke a Customer pairing link", + "description": "Revokes an open pairing link.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "pairingLinkId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "projectId", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/CustomerPairingLink" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/customers/{customerId}/numbers/{sessionId}/transfer": { + "post": { + "operationId": "transferCustomerNumber", + "tags": [ + "customers" + ], + "summary": "Transfer a Customer Number", + "description": "Atomically transfers one eligible Number from the explicitly confirmed source Customer to the destination Customer.\n\nRequires `customers:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "customers:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "customerId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + }, + { + "name": "Idempotency-Key", + "in": "header", + "required": true, + "schema": { + "type": "string", + "minLength": 1, + "maxLength": 255 + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransferCustomerNumberRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/CustomerNumber" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "409": { + "$ref": "#/components/responses/Conflict" + } + } + } + }, + "/platform/members": { + "get": { + "operationId": "listMembers", + "tags": [ + "members" + ], + "summary": "List members", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/members/invites": { + "post": { + "operationId": "inviteMember", + "tags": [ + "members" + ], + "summary": "Invite member", + "description": "**EXCLUDED from the public API** (`console`). Membership administration requires an authenticated console member.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Membership administration requires an authenticated console member.", + "x-dashboard-only": true, + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/members/{memberId}": { + "patch": { + "operationId": "updateMemberRole", + "tags": [ + "members" + ], + "summary": "Update member role", + "description": "**EXCLUDED from the public API** (`console`). Membership administration requires an authenticated console member.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Membership administration requires an authenticated console member.", + "x-dashboard-only": true, + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "memberId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "deleteMember", + "tags": [ + "members" + ], + "summary": "Delete member", + "description": "**EXCLUDED from the public API** (`console`). Membership administration requires an authenticated console member.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Membership administration requires an authenticated console member.", + "x-dashboard-only": true, + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "memberId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/keys": { + "get": { + "operationId": "listApiKeys", + "tags": [ + "keys" + ], + "summary": "List api keys", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/keys/{keyId}": { + "delete": { + "operationId": "deactivateApiKey", + "tags": [ + "keys" + ], + "summary": "Deactivate api key", + "description": "Public Management API. Requires a team API key with `sessions:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "keyId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/tokens": { + "get": { + "operationId": "listPolymorfaTokens", + "tags": [ + "tokens" + ], + "summary": "List polymorfa tokens", + "description": "Public Management API. Requires `sessions:read`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/audit": { + "get": { + "operationId": "listAuditLogs", + "tags": [ + "audit" + ], + "summary": "List audit logs", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/incidents": { + "get": { + "operationId": "listSecurityIncidents", + "tags": [ + "incidents" + ], + "summary": "List security incidents", + "description": "Public Management API. Requires a team API key with `sessions:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/incidents/{incidentId}/acknowledge": { + "post": { + "operationId": "acknowledgeSecurityIncident", + "tags": [ + "incidents" + ], + "summary": "Acknowledge security incident", + "description": "Public Management API. Requires a team API key with `sessions:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "sessions:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "incidentId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/media/{mediaId}": { + "get": { + "operationId": "getMediaUrl", + "tags": [ + "media" + ], + "summary": "Get media url", + "description": "Public Management API. Requires a team API key with `media:read`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "media:read", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "mediaId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "deleteMedia", + "tags": [ + "media" + ], + "summary": "Delete media", + "description": "Public Management API. Requires a team API key with `media:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "media:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "mediaId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/media/uploads": { + "post": { + "operationId": "createMediaUploadUrl", + "tags": [ + "media" + ], + "summary": "Create media upload url", + "description": "Public Management API. Requires a team API key with `media:manage`. Project tokens are not accepted.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "organization", + "x-excluded-from-public": false, + "x-required-scope": "media:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/platform/quicklink": { + "get": { + "operationId": "getQuickLinkSettings", + "tags": [ + "quicklink" + ], + "summary": "Read QuickLink settings", + "description": "Returns the saved QuickLink settings for the authenticated organization or one project, or null when nothing has been saved for that scope. There is no separate read permission: reading and updating both require `quicklink:manage`, because the settings include the redirect allowlist and branding that only a QuickLink manager should see.\n\nRequires `quicklink:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "quicklink:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/QuickLinkSettings" + } + ] + } + }, + "required": [ + "data" + ] + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + }, + "put": { + "operationId": "updateQuickLinkSettings", + "tags": [ + "quicklink" + ], + "summary": "Update QuickLink settings", + "description": "Updates the saved QuickLink settings for the authenticated organization or project and returns the saved record.\n\nRequires `quicklink:manage`. Project tokens only access resources in their own project.", + "x-audience": "public", + "x-polymorfa-resource-boundary": "project", + "x-excluded-from-public": false, + "x-required-scope": "quicklink:manage", + "security": [ + { + "ApiKeyAuth": [] + }, + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateQuickLinkSettingsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/QuickLinkSettings" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/console/keys": { + "post": { + "operationId": "mintForConsoleApiKey", + "tags": [ + "keys" + ], + "summary": "Mint for console api key", + "description": "**EXCLUDED from the public API** (`console`). Credential red line: a pmfa_ key must never mint a pmfa_ key. Human session only — keeps revocation meaningful.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Credential red line: a pmfa_ key must never mint a pmfa_ key. Human session only — keeps revocation meaningful.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/billing/topup": { + "post": { + "operationId": "topUpBilling", + "tags": [ + "billing" + ], + "summary": "Top up billing", + "description": "**EXCLUDED from the public API** (`console`). Starts a Stripe Checkout browser redirect; human session only. API clients use auto-top-up.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Starts a Stripe Checkout browser redirect; human session only. API clients use auto-top-up.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/organizations/{slug}": { + "get": { + "operationId": "getOrganizationBySlug", + "tags": [ + "organizations" + ], + "summary": "Get organization by slug", + "description": "**EXCLUDED from the public API** (`console`). Console org-switcher lookup; a key is already bound to one org.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Console org-switcher lookup; a key is already bound to one org.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "slug", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/organization/avatar/uploads": { + "post": { + "operationId": "generateOrganizationAvatarUploadUrl", + "tags": [ + "organization" + ], + "summary": "Generate organization avatar upload url", + "description": "**EXCLUDED from the public API** (`console`). Browser logo-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser logo-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/organization/avatar": { + "put": { + "operationId": "saveAvatarOrganization", + "tags": [ + "organization" + ], + "summary": "Save avatar organization", + "description": "**EXCLUDED from the public API** (`console`). Browser logo-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser logo-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "removeAvatarOrganization", + "tags": [ + "organization" + ], + "summary": "Remove avatar organization", + "description": "**EXCLUDED from the public API** (`console`). Browser logo-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser logo-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/organizations/ensure": { + "post": { + "operationId": "ensureForCurrentUserOrganization", + "tags": [ + "organizations" + ], + "summary": "Ensure for current user organization", + "description": "**EXCLUDED from the public API** (`console`). First-sign-in bootstrap for the session user.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "First-sign-in bootstrap for the session user.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/projects/{projectId}/icon": { + "post": { + "operationId": "generateProjectUploadUrl", + "tags": [ + "projects" + ], + "summary": "Generate project upload url", + "description": "**EXCLUDED from the public API** (`console`). Browser icon-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser icon-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/profile": { + "get": { + "operationId": "getUserProfile", + "tags": [ + "profile" + ], + "summary": "Get user profile", + "description": "**EXCLUDED from the public API** (`console`). 'Current user' only exists for a session; keys are org-scoped, not user-scoped.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "'Current user' only exists for a session; keys are org-scoped, not user-scoped.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "patch": { + "operationId": "updateUserProfileField", + "tags": [ + "profile" + ], + "summary": "Update user profile field", + "description": "**EXCLUDED from the public API** (`console`). Personal profile edit for the signed-in user.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Personal profile edit for the signed-in user.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/profile/ensure": { + "post": { + "operationId": "ensureProfileUserProfile", + "tags": [ + "profile" + ], + "summary": "Ensure profile user profile", + "description": "**EXCLUDED from the public API** (`console`). Sign-in bootstrap.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Sign-in bootstrap.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/teams": { + "get": { + "operationId": "listUserProfileTeams", + "tags": [ + "teams" + ], + "summary": "List user profile teams", + "description": "**EXCLUDED from the public API** (`console`). Session user's team switcher.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Session user's team switcher.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/profile/avatar/uploads": { + "post": { + "operationId": "generateUserProfileAvatarUploadUrl", + "tags": [ + "profile" + ], + "summary": "Generate user profile avatar upload url", + "description": "**EXCLUDED from the public API** (`console`). Browser avatar-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser avatar-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/profile/avatar": { + "put": { + "operationId": "saveAvatarUserProfile", + "tags": [ + "profile" + ], + "summary": "Save avatar user profile", + "description": "**EXCLUDED from the public API** (`console`). Browser avatar-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser avatar-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "removeAvatarUserProfile", + "tags": [ + "profile" + ], + "summary": "Remove avatar user profile", + "description": "**EXCLUDED from the public API** (`console`). Personal profile edit.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Personal profile edit.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/auth/methods": { + "get": { + "operationId": "getUserProfileAuthMethods", + "tags": [ + "auth" + ], + "summary": "Get user profile auth methods", + "description": "**EXCLUDED from the public API** (`console`). Account-security introspection for the session user.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Account-security introspection for the session user.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/auth/totp": { + "post": { + "operationId": "enrollTotpUserProfile", + "tags": [ + "auth" + ], + "summary": "Enroll totp user profile", + "description": "**EXCLUDED from the public API** (`console`). MFA enrollment via API key = account-takeover vector.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "MFA enrollment via API key = account-takeover vector.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/auth/totp/verify": { + "post": { + "operationId": "verifyTotpUserProfile", + "tags": [ + "auth" + ], + "summary": "Verify totp user profile", + "description": "**EXCLUDED from the public API** (`console`). Part of the human MFA step-up flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Part of the human MFA step-up flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/auth/factors/{factorId}": { + "delete": { + "operationId": "deleteUserProfileAuthFactor", + "tags": [ + "auth" + ], + "summary": "Delete user profile auth factor", + "description": "**EXCLUDED from the public API** (`console`). Removing MFA via API key = account-takeover vector.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Removing MFA via API key = account-takeover vector.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "factorId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/auth/providers": { + "get": { + "operationId": "getUserProfileProviderConnectionUrl", + "tags": [ + "auth" + ], + "summary": "Get user profile provider connection url", + "description": "**EXCLUDED from the public API** (`console`). Deferred Better Auth provider-link flow; dashboard identity only.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Deferred Better Auth provider-link flow; dashboard identity only.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/auth/providers/{provider}": { + "delete": { + "operationId": "disconnectProviderUserProfile", + "tags": [ + "auth" + ], + "summary": "Disconnect provider user profile", + "description": "**EXCLUDED from the public API** (`console`). Deferred Better Auth provider-unlink flow; dashboard identity only.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Deferred Better Auth provider-unlink flow; dashboard identity only.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "provider", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/teams/leave": { + "post": { + "operationId": "leaveTeamUserProfile", + "tags": [ + "teams" + ], + "summary": "Leave team user profile", + "description": "**EXCLUDED from the public API** (`console`). Acts on the session user's own membership.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Acts on the session user's own membership.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/teams/{teamId}/delete": { + "post": { + "operationId": "deleteUserProfileTeam", + "tags": [ + "teams" + ], + "summary": "Delete user profile team", + "description": "**EXCLUDED from the public API** (`console`). Destructive, human-confirmed flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Destructive, human-confirmed flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "teamId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications": { + "get": { + "operationId": "listNotificationInbox", + "tags": [ + "notifications" + ], + "summary": "List notification inbox", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/archived": { + "get": { + "operationId": "listNotificationArchived", + "tags": [ + "notifications" + ], + "summary": "List notification archived", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/count": { + "get": { + "operationId": "unreadCountNotification", + "tags": [ + "notifications" + ], + "summary": "Unread count notification", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/{notificationId}/read": { + "post": { + "operationId": "markReadNotification", + "tags": [ + "notifications" + ], + "summary": "Mark read notification", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "notificationId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/read": { + "post": { + "operationId": "markAllReadNotification", + "tags": [ + "notifications" + ], + "summary": "Mark all read notification", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/{notificationId}/archive": { + "post": { + "operationId": "archiveNotification", + "tags": [ + "notifications" + ], + "summary": "Archive notification", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "notificationId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/archive": { + "post": { + "operationId": "archiveAllNotification", + "tags": [ + "notifications" + ], + "summary": "Archive all notification", + "description": "**EXCLUDED from the public API** (`console`). User-scoped console inbox.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "User-scoped console inbox.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/preferences": { + "get": { + "operationId": "getNotificationPreferences", + "tags": [ + "notifications" + ], + "summary": "Get notification preferences", + "description": "**EXCLUDED from the public API** (`console`). Per-user notification preferences.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Per-user notification preferences.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "put": { + "operationId": "updateNotificationPreferences", + "tags": [ + "notifications" + ], + "summary": "Update notification preferences", + "description": "**EXCLUDED from the public API** (`console`). Per-user notification preferences.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Per-user notification preferences.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/notifications/test": { + "post": { + "operationId": "sendTestNotificationEmail", + "tags": [ + "notifications" + ], + "summary": "Send test notification email", + "description": "**EXCLUDED from the public API** (`console`). Console settings test button.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Console settings test button.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/quicklink/logo/uploads": { + "post": { + "operationId": "generateQuickLinkSettingsLogoUploadUrl", + "tags": [ + "quicklink" + ], + "summary": "Generate quick link settings logo upload url", + "description": "**EXCLUDED from the public API** (`console`). Browser logo-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser logo-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/quicklink/logo": { + "put": { + "operationId": "attachLogoQuickLinkSettings", + "tags": [ + "quicklink" + ], + "summary": "Attach logo quick link settings", + "description": "**EXCLUDED from the public API** (`console`). Browser logo-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser logo-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "removeLogoQuickLinkSettings", + "tags": [ + "quicklink" + ], + "summary": "Remove logo quick link settings", + "description": "**EXCLUDED from the public API** (`console`). Browser logo-upload flow.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Browser logo-upload flow.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/quicklink/logo/org": { + "post": { + "operationId": "useOrgLogoQuickLinkSettings", + "tags": [ + "quicklink" + ], + "summary": "Use org logo quick link settings", + "description": "**EXCLUDED from the public API** (`console`). Console snapshot flow (copies org logo).", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Console snapshot flow (copies org logo).", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/quicklink/logo/project": { + "post": { + "operationId": "useProjectIconQuickLinkSettings", + "tags": [ + "quicklink" + ], + "summary": "Use project icon quick link settings", + "description": "**EXCLUDED from the public API** (`console`). Console snapshot flow (copies project icon).", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Console snapshot flow (copies project icon).", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/webhooks": { + "get": { + "operationId": "listWebhooks", + "tags": [ + "webhooks" + ], + "summary": "List webhook endpoints", + "description": "Lists sanitized webhook endpoint settings for the authenticated organization.\n\nRequires a verified dashboard bearer and current organization authorization. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard webhook settings for the authenticated organization.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConsoleWebhook" + } + } + }, + "required": [ + "data" + ] + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + }, + "post": { + "operationId": "createWebhook", + "tags": [ + "webhooks" + ], + "summary": "Create a webhook endpoint", + "description": "Creates a webhook endpoint for the authenticated organization. Requires live owner or admin authority.\n\nRequires a verified dashboard bearer and current organization authorization. The signed-in member must be an organization owner or admin. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard webhook settings for the authenticated organization.", + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateConsoleWebhookRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ConsoleWebhook" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + } + } + } + }, + "/console/webhooks/{webhookId}": { + "patch": { + "operationId": "updateWebhook", + "tags": [ + "webhooks" + ], + "summary": "Update a webhook endpoint", + "description": "Updates a webhook endpoint in the authenticated organization. Requires live owner or admin authority.\n\nRequires a verified dashboard bearer and current organization authorization. The signed-in member must be an organization owner or admin. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard webhook settings for the authenticated organization.", + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateConsoleWebhookRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/ConsoleWebhook" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + }, + "delete": { + "operationId": "deleteWebhook", + "tags": [ + "webhooks" + ], + "summary": "Delete a webhook endpoint", + "description": "Deletes a webhook endpoint in the authenticated organization. Requires live owner or admin authority.\n\nRequires a verified dashboard bearer and current organization authorization. The signed-in member must be an organization owner or admin. Organization keys and project tokens are not accepted.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Dashboard webhook settings for the authenticated organization.", + "x-required-organization-role": "owner_or_admin", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "data": { + "$ref": "#/components/schemas/DeleteConsoleWebhookResult" + } + }, + "required": [ + "data" + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + } + } + } + }, + "/console/sandbox/pool": { + "get": { + "operationId": "getSandboxProjectPool", + "tags": [ + "sandbox" + ], + "summary": "Get sandbox project project pool", + "description": "**EXCLUDED from the public API** (`console`). Console/sandbox internal wiring.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Console/sandbox internal wiring.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/deployments": { + "get": { + "operationId": "listDeployments", + "tags": [ + "deployments" + ], + "summary": "List deployments", + "description": "**EXCLUDED from the public API** (`console`). Legacy console surface; not a customer contract.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Legacy console surface; not a customer contract.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/calls": { + "get": { + "operationId": "listCalls", + "tags": [ + "calls" + ], + "summary": "List calls", + "description": "**EXCLUDED from the public API** (`console`). Customer console view of the organization's own call records.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Customer console view of the organization's own call records.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "sessionId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/insights/logs": { + "get": { + "operationId": "logsInsight", + "tags": [ + "insights" + ], + "summary": "Logs insight", + "description": "**EXCLUDED from the public API** (`console`). Customer console observability for the selected organization and project.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Customer console observability for the selected organization and project.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/insights/usage": { + "get": { + "operationId": "usageInsight", + "tags": [ + "insights" + ], + "summary": "Usage insight", + "description": "**EXCLUDED from the public API** (`console`). Customer console usage and entitlement presentation.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Customer console usage and entitlement presentation.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/insights/analytics": { + "get": { + "operationId": "analyticsInsight", + "tags": [ + "insights" + ], + "summary": "Analytics insight", + "description": "**EXCLUDED from the public API** (`console`). Customer console aggregate product analytics; message bodies are never returned.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Customer console aggregate product analytics; message bodies are never returned.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "projectId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "start", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "end", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/insights/preferences": { + "get": { + "operationId": "getInsightPreferences", + "tags": [ + "insights" + ], + "summary": "Get insight preferences", + "description": "**EXCLUDED from the public API** (`console`). Organization analytics-consent controls for the console.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Organization analytics-consent controls for the console.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "put": { + "operationId": "updateInsightPreferences", + "tags": [ + "insights" + ], + "summary": "Update insight preferences", + "description": "**EXCLUDED from the public API** (`console`). Organization analytics-consent controls for the console.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Organization analytics-consent controls for the console.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/console/organization-invitations/{invitationId}/accept": { + "post": { + "operationId": "acceptOrganizationInvitation", + "tags": [ + "organization-invitations" + ], + "summary": "Accept organization invitation", + "description": "**EXCLUDED from the public API** (`console`). Deferred Better Auth invitation-acceptance flow; dashboard identity only.", + "x-audience": "console", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Deferred Better Auth invitation-acceptance flow; dashboard identity only.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "invitationId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/orgs": { + "get": { + "operationId": "adminListOrganizations", + "tags": [ + "admin/orgs" + ], + "summary": "List organizations", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/orgs/{orgId}": { + "get": { + "operationId": "adminGetOrganization", + "tags": [ + "admin/orgs" + ], + "summary": "Get organization", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "patch": { + "operationId": "adminRenameOrganization", + "tags": [ + "admin/orgs" + ], + "summary": "Rename organization", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "adminCascadeDeleteOrganization", + "tags": [ + "admin/orgs" + ], + "summary": "Cascade delete organization", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/orgs/{orgId}/freeze": { + "post": { + "operationId": "adminFreezeOrganization", + "tags": [ + "admin/orgs" + ], + "summary": "Freeze organization", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/orgs/{orgId}/unfreeze": { + "post": { + "operationId": "adminUnfreezeOrganization", + "tags": [ + "admin/orgs" + ], + "summary": "Unfreeze organization", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/orgs/features": { + "get": { + "operationId": "adminListOrganizationFeatureGroups", + "tags": [ + "admin/orgs" + ], + "summary": "List organization feature groups", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/orgs/{orgId}/features": { + "patch": { + "operationId": "adminSetOrganizationFeatureGroups", + "tags": [ + "admin/orgs" + ], + "summary": "Set organization feature groups", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/users": { + "get": { + "operationId": "adminSearchUser", + "tags": [ + "admin/users" + ], + "summary": "Search user", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/users/{userId}": { + "get": { + "operationId": "adminGetUser", + "tags": [ + "admin/users" + ], + "summary": "Get user", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/users/{userId}/onboarding": { + "delete": { + "operationId": "adminResetOnboardingUser", + "tags": [ + "admin/users" + ], + "summary": "Reset onboarding user", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/users/{userId}/suspend": { + "post": { + "operationId": "adminSuspendUser", + "tags": [ + "admin/users" + ], + "summary": "Suspend user user", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/users/{userId}/unsuspend": { + "post": { + "operationId": "adminUnsuspendUser", + "tags": [ + "admin/users" + ], + "summary": "Unsuspend user user", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/users/{userId}/signout": { + "post": { + "operationId": "adminForceSignOutUser", + "tags": [ + "admin/users" + ], + "summary": "Force sign out user", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "userId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/members/{memberId}": { + "patch": { + "operationId": "adminSetMemberRole", + "tags": [ + "admin/members" + ], + "summary": "Set member role", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "memberId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "delete": { + "operationId": "adminRemoveMember", + "tags": [ + "admin/members" + ], + "summary": "Remove member member", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "memberId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/members/invites": { + "post": { + "operationId": "adminInviteMember", + "tags": [ + "admin/members" + ], + "summary": "Invite member member", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/bansafe/enforcement/{orgId}/{sessionId}/lift": { + "post": { + "operationId": "adminLiftBanSafeEnforcement", + "tags": [ + "admin/bansafe" + ], + "summary": "Lift ban safe enforcement", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/bansafe/claims": { + "get": { + "operationId": "adminListBanSafeClaims", + "tags": [ + "admin/bansafe" + ], + "summary": "List ban safe claims", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "orgId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + "filed", + "under_review", + "approved", + "denied", + "paid", + "reversed" + ] + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 25 + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/bansafe/claims/{claimId}/approve": { + "post": { + "operationId": "adminApproveBanSafeClaim", + "tags": [ + "admin/bansafe" + ], + "summary": "Approve ban safe claim", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "claimId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/bansafe/claims/{claimId}/deny": { + "post": { + "operationId": "adminDenyBanSafeClaim", + "tags": [ + "admin/bansafe" + ], + "summary": "Deny ban safe claim", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "claimId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/bansafe/claims/{claimId}/reverse": { + "post": { + "operationId": "adminReverseBanSafeClaim", + "tags": [ + "admin/bansafe" + ], + "summary": "Reverse ban safe claim", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "claimId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/sessions": { + "get": { + "operationId": "adminListSessions", + "tags": [ + "admin/sessions" + ], + "summary": "List sessions", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/sessions/{sessionId}/stop": { + "post": { + "operationId": "adminForceStopSession", + "tags": [ + "admin/sessions" + ], + "summary": "Force stop session", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/sessions/{sessionId}": { + "delete": { + "operationId": "adminForceDeleteSession", + "tags": [ + "admin/sessions" + ], + "summary": "Force delete session", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/sessions/{sessionId}/comp": { + "post": { + "operationId": "adminCompSessionDaySession", + "tags": [ + "admin/sessions" + ], + "summary": "Comp session day session", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "description": "Database session UUID or stable session slug.", + "schema": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/campaigns": { + "get": { + "operationId": "adminListCampaigns", + "tags": [ + "admin/campaigns" + ], + "summary": "List campaigns", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/campaigns/{campaignId}/pause": { + "post": { + "operationId": "adminForcePauseCampaign", + "tags": [ + "admin/campaigns" + ], + "summary": "Force pause campaign", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/campaigns/{campaignId}/stop": { + "post": { + "operationId": "adminForceStopCampaign", + "tags": [ + "admin/campaigns" + ], + "summary": "Force stop campaign", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "campaignId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/campaigns/optouts": { + "get": { + "operationId": "adminOptOutLeaderboardCampaign", + "tags": [ + "admin/campaigns" + ], + "summary": "Opt out leaderboard campaign", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/billing/revenue": { + "get": { + "operationId": "adminPlatformRevenueBilling", + "tags": [ + "admin/billing" + ], + "summary": "Platform revenue billing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/billing/leaderboard": { + "get": { + "operationId": "adminTopOrgsByRevenueBilling", + "tags": [ + "admin/billing" + ], + "summary": "Top orgs by revenue billing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/billing/lowbalance": { + "get": { + "operationId": "adminLowBalanceOrgsBilling", + "tags": [ + "admin/billing" + ], + "summary": "Low balance orgs billing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/billing/credits": { + "post": { + "operationId": "adminCompCreditsBilling", + "tags": [ + "admin/billing" + ], + "summary": "Comp credits billing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/billing/refunds": { + "post": { + "operationId": "adminRefundBilling", + "tags": [ + "admin/billing" + ], + "summary": "Refund billing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/keys": { + "get": { + "operationId": "adminListApiKeys", + "tags": [ + "admin/keys" + ], + "summary": "List api keys", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/keys/{keyId}": { + "delete": { + "operationId": "adminRevokeApiKeyApiKey", + "tags": [ + "admin/keys" + ], + "summary": "Revoke api key api key", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "keyId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/tenants": { + "get": { + "operationId": "adminListTenants", + "tags": [ + "admin/tenants" + ], + "summary": "List tenants", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/tenants/{tenantId}": { + "patch": { + "operationId": "adminSetTenantActive", + "tags": [ + "admin/tenants" + ], + "summary": "Set tenant active", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-merged-endpoints": [ + "adminUpdateTenantRateLimits", + "adminUpdateTenantLogLevel", + "adminToggleDebugModeTenant" + ], + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "tenantId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/pricing": { + "get": { + "operationId": "adminListPricing", + "tags": [ + "admin/pricing" + ], + "summary": "List pricing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/pricing/{tier}": { + "put": { + "operationId": "adminUpdatePricing", + "tags": [ + "admin/pricing" + ], + "summary": "Update pricing", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "tier", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "patch": { + "operationId": "adminSetPricingActive", + "tags": [ + "admin/pricing" + ], + "summary": "Set pricing active", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "tier", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/organization-invitations": { + "get": { + "operationId": "adminListOrganizationInvitations", + "tags": [ + "admin/organization-invitations" + ], + "summary": "List organization invitations", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + }, + "post": { + "operationId": "adminCreateOrganizationInvitation", + "tags": [ + "admin/organization-invitations" + ], + "summary": "Create organization invitation", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/organization-invitations/{invitationId}": { + "delete": { + "operationId": "adminRevokeOrganizationInvitation", + "tags": [ + "admin/organization-invitations" + ], + "summary": "Revoke organization invitation", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "invitationId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/webhooks": { + "get": { + "operationId": "adminListWebhooks", + "tags": [ + "admin/webhooks" + ], + "summary": "List webhooks", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/webhooks/{webhookId}/disable": { + "post": { + "operationId": "adminForceDisableWebhook", + "tags": [ + "admin/webhooks" + ], + "summary": "Force disable webhook", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "parameters": [ + { + "name": "webhookId", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/audit": { + "get": { + "operationId": "adminListAuditLogGlobal", + "tags": [ + "admin/audit" + ], + "summary": "List audit log global", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/audit/actions": { + "get": { + "operationId": "adminListAuditLogAdminActions", + "tags": [ + "admin/audit" + ], + "summary": "List audit log admin actions", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/kpis": { + "get": { + "operationId": "adminPlatformKpisPlatform", + "tags": [ + "admin/kpis" + ], + "summary": "Platform kpis platform", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/signups": { + "get": { + "operationId": "adminRecentSignupsPlatform", + "tags": [ + "admin/signups" + ], + "summary": "Recent signups platform", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/sync": { + "post": { + "operationId": "adminEnsureCurrentUserStaffSyncStaffSync", + "tags": [ + "admin/sync" + ], + "summary": "Ensure current user staff sync staff sync", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + }, + "/admin/bans": { + "get": { + "operationId": "adminListRecentSessionBans", + "tags": [ + "admin/bans" + ], + "summary": "List recent session bans", + "description": "**EXCLUDED from the public API** (`staff`). Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "x-audience": "staff", + "x-polymorfa-resource-boundary": "human_only", + "x-excluded-from-public": true, + "x-exclusion-reason": "Polymorfa staff endpoint (cross-org / platform control). Requires a staff dashboard identity; never key-authenticated.", + "security": [ + { + "ConsoleSession": [] + } + ], + "responses": { + "200": { + "description": "Success", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataEnvelope" + } + } + } + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "501": { + "$ref": "#/components/responses/NotImplemented" + } + } + } + } + }, + "components": { + "securitySchemes": { + "ApiKeyAuth": { + "type": "http", + "scheme": "bearer", + "description": "Polymorfa server credential: a scoped pmfa_ organization key, or a pmfa_pt_ project token on project- and session-bound operations inside its exact authenticated project. Keys may be personal or service-account owned. Both enforce selected action scopes; organization keys can address team resources and every project in the organization. Listener and browser client credentials are rejected." + }, + "ConsoleSession": { + "type": "http", + "scheme": "bearer", + "description": "Verified dashboard JWT for signed-in Console requests. This is not a server credential." + } + }, + "schemas": { + "DataEnvelope": { + "type": "object", + "properties": { + "data": { + "description": "Operation result." + } + }, + "required": [ + "data" + ] + }, + "ErrorEnvelope": { + "type": "object", + "required": [ + "error", + "data", + "docs" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "type", + "code", + "message", + "param" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "invalid_request_error", + "authentication_error", + "permission_error", + "conflict_error", + "rate_limit_error", + "api_error", + "upstream_error" + ] + }, + "code": { + "type": "string", + "description": "Stable failure code. Use this value for programmatic handling." + }, + "message": { + "type": "string", + "description": "Safe explanation of the failure." + }, + "param": { + "type": "string", + "nullable": true, + "description": "Invalid request field, or null when no field applies." + } + } + }, + "data": { + "type": "string", + "nullable": true, + "enum": [ + null + ], + "description": "Always null for a failed request." + }, + "docs": { + "type": "string", + "format": "uri", + "description": "Documentation link to this failure code." + } + } + }, + "ProjectId": { + "type": "string", + "format": "uuid", + "description": "Project UUID. Optional where an operation can infer or search organization scope; required where the operation creates a project-owned resource." + }, + "CustomerId": { + "type": "string", + "format": "uuid", + "description": "Project-owned Customer UUID." + }, + "Customer": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "$ref": "#/components/schemas/CustomerId" + }, + "orgId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "name": { + "type": "string", + "nullable": true, + "maxLength": 120 + }, + "phone": { + "type": "string", + "nullable": true, + "pattern": "^\\+[1-9][0-9]{6,14}$" + }, + "externalCustomerId": { + "type": "string", + "nullable": true, + "maxLength": 200 + }, + "status": { + "type": "string", + "enum": [ + "active", + "archiving", + "archived" + ] + }, + "isDefault": { + "type": "boolean" + }, + "archivedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "createdAt": { + "type": "integer", + "format": "int64" + }, + "updatedAt": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "id", + "orgId", + "projectId", + "name", + "phone", + "externalCustomerId", + "status", + "isDefault", + "archivedAt", + "createdAt", + "updatedAt" + ] + }, + "CustomerSummary": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "$ref": "#/components/schemas/CustomerId" + }, + "orgId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "name": { + "type": "string", + "nullable": true, + "maxLength": 120 + }, + "phoneMasked": { + "type": "string", + "nullable": true + }, + "externalCustomerId": { + "type": "string", + "nullable": true, + "maxLength": 200 + }, + "status": { + "type": "string", + "enum": [ + "active", + "archiving", + "archived" + ] + }, + "isDefault": { + "type": "boolean" + }, + "archivedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "numberCount": { + "type": "integer", + "minimum": 0 + }, + "connectedNumberCount": { + "type": "integer", + "minimum": 0 + }, + "activePairingLinkState": { + "type": "string", + "nullable": true + }, + "lastActivityAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "needsAttention": { + "type": "boolean" + }, + "createdAt": { + "type": "integer", + "format": "int64" + }, + "updatedAt": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "id", + "orgId", + "projectId", + "name", + "phoneMasked", + "externalCustomerId", + "status", + "isDefault", + "archivedAt", + "numberCount", + "connectedNumberCount", + "activePairingLinkState", + "lastActivityAt", + "needsAttention", + "createdAt", + "updatedAt" + ] + }, + "CustomersStatus": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "enabledAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "enabledBy": { + "type": "string", + "nullable": true + }, + "defaultCustomer": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Customer" + } + ], + "nullable": true + } + }, + "required": [ + "enabled", + "enabledAt", + "enabledBy", + "defaultCustomer" + ] + }, + "CustomersEnablement": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "enabledAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "enabledBy": { + "type": "string", + "nullable": true + }, + "defaultCustomer": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/Customer" + } + ], + "nullable": true + }, + "migratedNumberCount": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "enabled", + "enabledAt", + "enabledBy", + "defaultCustomer", + "migratedNumberCount" + ] + }, + "CustomerProjectRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + } + } + }, + "CreateCustomerRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 120 + }, + "phone": { + "type": "string", + "nullable": true, + "description": "Phone number normalized to E.164." + }, + "externalCustomerId": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 200 + } + } + }, + "UpdateCustomerRequest": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "name": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 120 + }, + "phone": { + "type": "string", + "nullable": true, + "description": "Phone number normalized to E.164." + }, + "externalCustomerId": { + "type": "string", + "nullable": true, + "minLength": 1, + "maxLength": 200 + } + } + }, + "CustomerNumber": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "customerId": { + "$ref": "#/components/schemas/CustomerId" + }, + "sessionId": { + "type": "string" + }, + "name": { + "type": "string", + "nullable": true + }, + "phoneMasked": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string" + }, + "backend": { + "type": "string", + "nullable": true + }, + "createdAt": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "id", + "customerId", + "sessionId", + "name", + "phoneMasked", + "status", + "backend", + "createdAt" + ] + }, + "CustomerEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "action": { + "type": "string", + "pattern": "^customer(?:\\.[a-z0-9_]+){1,3}$", + "maxLength": 128 + }, + "fromStatus": { + "type": "string", + "nullable": true + }, + "toStatus": { + "type": "string", + "nullable": true + }, + "sessionId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "pairingLinkId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "metadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "fields": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "name", + "phone", + "externalCustomerId" + ] + } + } + } + }, + "occurredAt": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "id", + "action", + "fromStatus", + "toStatus", + "sessionId", + "pairingLinkId", + "metadata", + "occurredAt" + ] + }, + "CustomerPairingLink": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "orgId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "customerId": { + "$ref": "#/components/schemas/CustomerId" + }, + "expectedPhoneMasked": { + "type": "string", + "nullable": true + }, + "methods": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "qr", + "phone" + ] + } + }, + "locale": { + "type": "string", + "enum": [ + "en", + "pt-BR", + null + ], + "nullable": true + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system", + null + ], + "nullable": true + }, + "expiresAt": { + "type": "integer", + "format": "int64" + }, + "status": { + "type": "string", + "enum": [ + "active", + "opened", + "connecting", + "connected", + "failed", + "expired", + "revoked" + ] + }, + "attemptCount": { + "type": "integer", + "minimum": 0 + }, + "maxAttempts": { + "type": "integer", + "minimum": 1, + "maximum": 20 + }, + "pendingSessionId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "createdBy": { + "type": "string", + "nullable": true + }, + "reservedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "openedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "connectingAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "connectedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "failedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "expiredAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "revokedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "lastErrorCode": { + "type": "string", + "nullable": true + }, + "failedExchangeCount": { + "type": "integer", + "minimum": 0, + "maximum": 5 + }, + "phoneMismatchCount": { + "type": "integer", + "minimum": 0, + "maximum": 3 + }, + "createdAt": { + "type": "integer", + "format": "int64" + }, + "updatedAt": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "id", + "orgId", + "projectId", + "customerId", + "expectedPhoneMasked", + "methods", + "locale", + "theme", + "expiresAt", + "status", + "attemptCount", + "maxAttempts", + "pendingSessionId", + "createdBy", + "reservedAt", + "openedAt", + "connectingAt", + "connectedAt", + "failedAt", + "expiredAt", + "revokedAt", + "lastErrorCode", + "failedExchangeCount", + "phoneMismatchCount", + "createdAt", + "updatedAt" + ] + }, + "CreatedCustomerPairingLink": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "orgId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "customerId": { + "$ref": "#/components/schemas/CustomerId" + }, + "expectedPhoneMasked": { + "type": "string", + "nullable": true + }, + "methods": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "qr", + "phone" + ] + } + }, + "locale": { + "type": "string", + "enum": [ + "en", + "pt-BR", + null + ], + "nullable": true + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system", + null + ], + "nullable": true + }, + "expiresAt": { + "type": "integer", + "format": "int64" + }, + "status": { + "type": "string", + "enum": [ + "active", + "opened", + "connecting", + "connected", + "failed", + "expired", + "revoked" + ] + }, + "attemptCount": { + "type": "integer", + "minimum": 0 + }, + "maxAttempts": { + "type": "integer", + "minimum": 1, + "maximum": 20 + }, + "pendingSessionId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "createdBy": { + "type": "string", + "nullable": true + }, + "reservedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "openedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "connectingAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "connectedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "failedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "expiredAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "revokedAt": { + "type": "integer", + "format": "int64", + "nullable": true + }, + "lastErrorCode": { + "type": "string", + "nullable": true + }, + "failedExchangeCount": { + "type": "integer", + "minimum": 0, + "maximum": 5 + }, + "phoneMismatchCount": { + "type": "integer", + "minimum": 0, + "maximum": 3 + }, + "createdAt": { + "type": "integer", + "format": "int64" + }, + "updatedAt": { + "type": "integer", + "format": "int64" + }, + "url": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "Returned once; null on an idempotent replay." + } + }, + "required": [ + "id", + "orgId", + "projectId", + "customerId", + "expectedPhoneMasked", + "methods", + "locale", + "theme", + "expiresAt", + "status", + "attemptCount", + "maxAttempts", + "pendingSessionId", + "createdBy", + "reservedAt", + "openedAt", + "connectingAt", + "connectedAt", + "failedAt", + "expiredAt", + "revokedAt", + "lastErrorCode", + "failedExchangeCount", + "phoneMismatchCount", + "createdAt", + "updatedAt", + "url" + ] + }, + "CreateCustomerPairingLinkRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "expectedPhone": { + "type": "string", + "nullable": true, + "description": "Optional expected phone, normalized to E.164." + }, + "methods": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "qr", + "phone" + ] + } + }, + "expiresInSeconds": { + "type": "integer", + "minimum": 900, + "maximum": 604800, + "default": 86400 + }, + "locale": { + "type": "string", + "enum": [ + "en", + "pt-BR", + null + ], + "nullable": true + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system", + null + ], + "nullable": true + } + } + }, + "TransferCustomerNumberRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "sourceCustomerId": { + "$ref": "#/components/schemas/CustomerId" + }, + "confirm": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "projectId", + "sourceCustomerId", + "confirm" + ] + }, + "TemplateId": { + "type": "string", + "format": "uuid", + "description": "Message-template draft UUID." + }, + "ConsoleWebhookRetry": { + "type": "object", + "additionalProperties": false, + "properties": { + "attempts": { + "type": "integer", + "minimum": 0, + "maximum": 10 + }, + "delaySeconds": { + "type": "integer", + "minimum": 0, + "maximum": 3600 + }, + "policy": { + "type": "string", + "enum": [ + "constant", + "linear", + "exponential" + ] + } + }, + "required": [ + "attempts", + "delaySeconds", + "policy" + ] + }, + "ConsoleWebhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "url": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://", + "minLength": 1, + "maxLength": 2048, + "description": "Public HTTP(S) endpoint. Private, reserved, link-local, multicast, and credential-bearing targets are rejected." + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "retries": { + "$ref": "#/components/schemas/ConsoleWebhookRetry" + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "hasSigningSecret": { + "type": "boolean" + } + }, + "required": [ + "id", + "url", + "events", + "retries", + "enabled", + "format", + "createdAt", + "hasSigningSecret" + ] + }, + "CreateConsoleWebhookRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://", + "minLength": 1, + "maxLength": 2048, + "description": "Public HTTP(S) endpoint. Private, reserved, link-local, multicast, and credential-bearing targets are rejected." + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "retries": { + "$ref": "#/components/schemas/ConsoleWebhookRetry" + }, + "signingSecret": { + "type": "string", + "minLength": 16, + "maxLength": 4096, + "writeOnly": true + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ], + "default": "native" + } + }, + "required": [ + "url" + ] + }, + "UpdateConsoleWebhookRequest": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "url": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://", + "minLength": 1, + "maxLength": 2048, + "description": "Public HTTP(S) endpoint. Private, reserved, link-local, multicast, and credential-bearing targets are rejected." + }, + "events": { + "type": "array", + "items": { + "type": "string" + } + }, + "retries": { + "$ref": "#/components/schemas/ConsoleWebhookRetry" + }, + "signingSecret": { + "type": "string", + "minLength": 16, + "maxLength": 4096, + "writeOnly": true + }, + "clearSigningSecret": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + } + }, + "not": { + "required": [ + "signingSecret", + "clearSigningSecret" + ], + "properties": { + "clearSigningSecret": { + "enum": [ + true + ] + } + } + } + }, + "DeleteConsoleWebhookResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "removed": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "removed" + ] + }, + "QuickLinkSettings": { + "type": "object", + "additionalProperties": false, + "description": "Saved QuickLink settings for one scope. `logoUrl` is a short-lived read URL for the saved logo.", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "enabled": { + "type": "boolean" + }, + "allowedRedirectUris": { + "type": "array", + "items": { + "type": "string" + } + }, + "businessName": { + "type": "string", + "nullable": true + }, + "headline": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string", + "nullable": true + }, + "successMessage": { + "type": "string", + "nullable": true + }, + "supportUrl": { + "type": "string", + "nullable": true + }, + "privacyUrl": { + "type": "string", + "nullable": true + }, + "termsUrl": { + "type": "string", + "nullable": true + }, + "accent": { + "type": "string", + "nullable": true + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system" + ] + }, + "hideWatermark": { + "type": "boolean" + }, + "shape": { + "type": "string", + "enum": [ + "square", + "rounded", + "pill", + null + ], + "nullable": true + }, + "radiusPx": { + "type": "number", + "nullable": true + }, + "logoMode": { + "type": "string", + "enum": [ + "none", + "custom", + "organization", + "project" + ] + }, + "logoStorageId": { + "type": "string", + "nullable": true + }, + "logoSourceStorageId": { + "type": "string", + "nullable": true + }, + "logoUrl": { + "type": "string", + "nullable": true + }, + "historySync": { + "type": "string", + "enum": [ + "ask", + "force_on", + "force_off" + ] + }, + "methods": { + "type": "array", + "nullable": true, + "items": { + "type": "string", + "enum": [ + "qr", + "pairing" + ] + } + }, + "defaultMethod": { + "type": "string", + "enum": [ + "qr", + "pairing", + null + ], + "nullable": true + }, + "createdAt": { + "type": "integer" + }, + "updatedAt": { + "type": "integer" + } + }, + "required": [ + "id", + "projectId", + "enabled", + "allowedRedirectUris", + "businessName", + "headline", + "description", + "successMessage", + "supportUrl", + "privacyUrl", + "termsUrl", + "accent", + "theme", + "hideWatermark", + "shape", + "radiusPx", + "logoMode", + "logoStorageId", + "logoSourceStorageId", + "logoUrl", + "historySync", + "methods", + "defaultMethod", + "createdAt", + "updatedAt" + ] + }, + "UpdateQuickLinkSettingsRequest": { + "type": "object", + "additionalProperties": false, + "description": "QuickLink settings for the organization or one project. Omitted fields keep their saved value; `null` clears an optional field.", + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "enabled": { + "type": "boolean", + "description": "Allows QuickLinks to be created for the scope." + }, + "allowedRedirectUris": { + "type": "array", + "maxItems": 50, + "items": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]://", + "maxLength": 2048 + }, + "description": "Up to 50 exact HTTPS callback URLs without credentials. A QuickLink callbackUrl must match one of them." + }, + "businessName": { + "type": "string", + "maxLength": 120, + "nullable": true + }, + "headline": { + "type": "string", + "maxLength": 80, + "nullable": true, + "description": "Page title shown above the pairing flow. Defaults to “Connect WhatsApp”." + }, + "description": { + "type": "string", + "maxLength": 280, + "nullable": true, + "description": "Intro sentence shown under the headline." + }, + "successMessage": { + "type": "string", + "maxLength": 280, + "nullable": true, + "description": "Message shown after the number connects." + }, + "supportUrl": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]://", + "maxLength": 2048, + "nullable": true, + "description": "Help link shown on the page." + }, + "privacyUrl": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]://", + "maxLength": 2048, + "nullable": true, + "description": "Privacy policy link shown on the consent step." + }, + "termsUrl": { + "type": "string", + "format": "uri", + "pattern": "^[Hh][Tt][Tt][Pp][Ss]://", + "maxLength": 2048, + "nullable": true, + "description": "Terms link shown on the consent step." + }, + "accent": { + "type": "string", + "pattern": "^#[0-9A-Fa-f]{6}$", + "nullable": true + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark", + "system" + ] + }, + "hideWatermark": { + "type": "boolean" + }, + "shape": { + "type": "string", + "enum": [ + "square", + "rounded", + "pill", + null + ], + "nullable": true + }, + "radiusPx": { + "type": "number", + "minimum": 0, + "maximum": 999, + "nullable": true + }, + "logoMode": { + "type": "string", + "enum": [ + "none", + "custom", + "organization", + "project" + ] + }, + "logoStorageId": { + "type": "string", + "nullable": true + }, + "logoSourceStorageId": { + "type": "string", + "nullable": true + }, + "historySync": { + "type": "string", + "enum": [ + "ask", + "force_on", + "force_off" + ] + }, + "methods": { + "type": "array", + "nullable": true, + "minItems": 1, + "maxItems": 2, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "qr", + "pairing" + ] + }, + "description": "Connection methods offered on hosted QuickLink pages." + }, + "defaultMethod": { + "type": "string", + "enum": [ + "qr", + "pairing", + null + ], + "nullable": true, + "description": "Method the page opens first. Unset lets the page choose by device." + } + } + }, + "FlowId": { + "type": "string", + "format": "uuid", + "description": "Polymorfa Flow draft UUID." + }, + "FlowSummary": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "$ref": "#/components/schemas/FlowId" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 120 + }, + "status": { + "type": "string", + "enum": [ + "draft", + "ready", + "archived" + ] + }, + "version": { + "type": "string" + }, + "screenCount": { + "type": "integer", + "minimum": 0, + "maximum": 50 + }, + "metaLinks": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + }, + "createdAt": { + "type": "integer", + "format": "int64", + "minimum": 0 + }, + "updatedAt": { + "type": "integer", + "format": "int64", + "minimum": 0 + } + }, + "required": [ + "id", + "name", + "status", + "version", + "screenCount", + "metaLinks", + "createdAt", + "updatedAt" + ] + }, + "FlowDraft": { + "allOf": [ + { + "$ref": "#/components/schemas/FlowSummary" + }, + { + "type": "object", + "properties": { + "definition": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "definition" + ] + } + ] + }, + "CreateFlowRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "draftId": { + "$ref": "#/components/schemas/FlowId" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 120 + }, + "definition": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "projectId", + "name", + "definition" + ] + }, + "UpdateFlowRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "expectedUpdatedAt": { + "type": "integer", + "format": "int64", + "minimum": 0 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 120 + }, + "status": { + "type": "string", + "enum": [ + "draft", + "ready", + "archived" + ] + }, + "definition": { + "type": "object", + "additionalProperties": true + } + }, + "required": [ + "projectId", + "expectedUpdatedAt" + ] + }, + "DeleteFlowResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "ok" + ] + }, + "ManagementTemplate": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "$ref": "#/components/schemas/TemplateId" + }, + "createdAt": { + "type": "integer", + "format": "int64", + "minimum": 0 + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 512 + }, + "category": { + "type": "string" + }, + "language": { + "type": "string" + }, + "status": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "definition": { + "type": "object", + "additionalProperties": true, + "nullable": true + }, + "sampleValues": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "nullable": true + }, + "cloudLinks": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + }, + "updatedAt": { + "type": "integer", + "format": "int64", + "minimum": 0 + } + }, + "required": [ + "id", + "createdAt", + "name", + "category", + "language", + "status", + "kind", + "definition", + "sampleValues", + "cloudLinks", + "updatedAt" + ] + }, + "CreateManagementTemplateRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "draftId": { + "$ref": "#/components/schemas/TemplateId" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 512 + }, + "definition": { + "type": "object", + "additionalProperties": true + }, + "sampleValues": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "projectId", + "name", + "definition" + ] + }, + "UpdateManagementTemplateRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 512 + }, + "status": { + "type": "string" + }, + "definition": { + "type": "object", + "additionalProperties": true + }, + "sampleValues": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "nullable": true + } + }, + "required": [ + "projectId" + ] + }, + "DeleteManagementTemplateResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "ok": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "ok" + ] + }, + "SessionIdentifier": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "description": "Database session UUID or stable session slug." + }, + "SessionProjectContext": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + } + } + }, + "SessionTierOverrideRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "tierOverride": { + "type": "string", + "enum": [ + "free", + "standard", + "pro", + null + ], + "nullable": true + } + }, + "required": [ + "tierOverride" + ] + }, + "SessionBatchRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "sessionIds": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "$ref": "#/components/schemas/SessionIdentifier" + } + }, + "ids": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "deprecated": true, + "description": "Compatibility alias for sessionIds.", + "items": { + "$ref": "#/components/schemas/SessionIdentifier" + } + } + }, + "anyOf": [ + { + "required": [ + "sessionIds" + ] + }, + { + "required": [ + "ids" + ] + } + ] + }, + "CreateTestingNumberRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "customerId": { + "type": "string", + "format": "uuid", + "description": "Customer owner. Defaults to the protected Default customer when Customers is enabled." + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 100, + "description": "Optional Console display name." + }, + "country": { + "type": "string", + "enum": [ + "ES", + "DE", + "MX", + "GB", + "SA", + "IT", + "AF", + "AX", + "AL", + "DZ", + "AS", + "AD", + "AO", + "AI", + "AG", + "AR", + "AM", + "AW", + "AC", + "AU", + "AT", + "AZ", + "BS", + "BH", + "BD", + "BB", + "BY", + "BE", + "BZ", + "BJ", + "BM", + "BT", + "BO", + "BQ", + "BA", + "BW", + "BR", + "IO", + "VG", + "BN", + "BG", + "BF", + "BI", + "CI", + "KH", + "CM", + "CA", + "CV", + "KY", + "CF", + "TD", + "CL", + "CN", + "CX", + "CC", + "CO", + "KM", + "CG", + "CD", + "CK", + "CR", + "HR", + "CU", + "CW", + "CY", + "CZ", + "DK", + "DJ", + "DM", + "DO", + "EC", + "EG", + "SV", + "GQ", + "ER", + "EE", + "ET", + "FK", + "FO", + "FJ", + "FI", + "FR", + "GF", + "PF", + "GA", + "GM", + "GE", + "GH", + "GI", + "GR", + "GL", + "GD", + "GP", + "GU", + "GT", + "GG", + "GN", + "GW", + "GY", + "HT", + "HN", + "HK", + "HU", + "IS", + "IN", + "ID", + "IR", + "IQ", + "IE", + "IM", + "IL", + "JM", + "JP", + "JE", + "JO", + "KZ", + "KE", + "KI", + "KW", + "KG", + "LA", + "LV", + "LB", + "LS", + "LR", + "LY", + "LI", + "LT", + "LU", + "MO", + "MK", + "MG", + "MW", + "MY", + "MV", + "ML", + "MT", + "MH", + "MQ", + "MR", + "MU", + "YT", + "FM", + "MD", + "MC", + "MN", + "ME", + "MS", + "MA", + "MZ", + "MM", + "NA", + "NR", + "NP", + "NL", + "NC", + "NZ", + "NI", + "NE", + "NG", + "NU", + "NF", + "KP", + "MP", + "NO", + "OM", + "PK", + "PW", + "PS", + "PA", + "PG", + "PY", + "PE", + "PH", + "PL", + "PT", + "PR", + "QA", + "RO", + "RU", + "RW", + "RE", + "BL", + "SH", + "KN", + "LC", + "MF", + "PM", + "VC", + "WS", + "SM", + "SN", + "RS", + "SC", + "SL", + "SG", + "SX", + "SK", + "SI", + "SB", + "SO", + "ZA", + "KR", + "SS", + "LK", + "SD", + "SR", + "SJ", + "SZ", + "SE", + "CH", + "SY", + "ST", + "TW", + "TJ", + "TZ", + "TH", + "TL", + "TG", + "TK", + "TO", + "TT", + "TN", + "TR", + "TM", + "TC", + "TV", + "VI", + "UG", + "UA", + "AE", + "US", + "UY", + "UZ", + "VU", + "VA", + "VE", + "VN", + "WF", + "YE", + "ZM", + "ZW", + "XK" + ], + "default": "US", + "description": "WhatsApp-supported ISO 3166-1 alpha-2 country used to generate a realistic E.164 identity." + } + }, + "required": [ + "projectId" + ] + }, + "ManagedSession": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "sessionId": { + "type": "string", + "description": "Stable session slug." + }, + "status": { + "type": "string" + }, + "tierOverride": { + "type": "string", + "enum": [ + "free", + "standard", + "pro", + null + ], + "nullable": true + } + }, + "required": [ + "id", + "sessionId", + "status", + "tierOverride" + ] + }, + "PlatformSession": { + "type": "object", + "additionalProperties": false, + "properties": { + "_id": { + "type": "string", + "format": "uuid" + }, + "_creationTime": { + "type": "number", + "description": "Creation time as Unix epoch milliseconds." + }, + "projectId": { + "$ref": "#/components/schemas/ProjectId" + }, + "sessionId": { + "$ref": "#/components/schemas/SessionIdentifier" + }, + "name": { + "type": "string", + "nullable": true + }, + "phone": { + "type": "string", + "nullable": true + }, + "platform": { + "type": "string", + "nullable": true + }, + "isBusiness": { + "type": "boolean" + }, + "testMode": { + "type": "boolean" + }, + "tierOverride": { + "type": "string", + "enum": [ + "free", + "standard", + "pro", + "scale", + null + ], + "nullable": true + }, + "status": { + "type": "string", + "description": "Latest runtime connection status." + }, + "statusReason": { + "type": "string", + "nullable": true, + "description": "Machine-readable reason for the latest connection status, when available." + }, + "messageCount": { + "type": "integer", + "minimum": 0 + }, + "lastActiveAt": { + "type": "number", + "nullable": true, + "description": "Last activity time as Unix epoch milliseconds." + }, + "customer": { + "type": "object", + "nullable": true, + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string", + "nullable": true + }, + "isDefault": { + "type": "boolean" + } + }, + "required": [ + "id", + "name", + "isDefault" + ] + }, + "claim": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "kind": { + "type": "string", + "enum": [ + "unclaimed" + ] + } + }, + "required": [ + "kind" + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "kind": { + "type": "string", + "enum": [ + "claimed-elsewhere" + ] + }, + "displayName": { + "type": "string" + }, + "avatarUrl": { + "type": "string", + "nullable": true + }, + "avatarSeed": { + "type": "string" + }, + "claimedAt": { + "type": "number" + } + }, + "required": [ + "kind", + "displayName", + "avatarUrl", + "avatarSeed", + "claimedAt" + ] + } + ] + } + }, + "required": [ + "_id", + "_creationTime", + "projectId", + "sessionId", + "name", + "phone", + "platform", + "isBusiness", + "testMode", + "tierOverride", + "status", + "statusReason", + "messageCount", + "lastActiveAt", + "customer", + "claim" + ] + }, + "SessionStopResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "stopping": { + "type": "boolean", + "enum": [ + true + ] + }, + "sessionId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "stopping", + "sessionId" + ] + }, + "SessionStartResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "starting": { + "type": "boolean", + "enum": [ + true + ] + }, + "sessionId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "starting", + "sessionId" + ] + }, + "SessionRemoveResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "removed": { + "type": "boolean", + "enum": [ + true + ] + }, + "sessionId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "removed", + "sessionId" + ] + }, + "SessionBatchStopResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "stopping": { + "type": "integer", + "minimum": 0, + "maximum": 100 + } + }, + "required": [ + "stopping" + ] + }, + "SessionBatchRemoveResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "removed": { + "type": "integer", + "minimum": 0, + "maximum": 100 + } + }, + "required": [ + "removed" + ] + }, + "TestingSessionId": { + "type": "string", + "pattern": "^test_[A-Za-z0-9_-]{16}$", + "description": "Generated testing-session slug." + }, + "ProductionEnrollmentRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "business": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 2, + "maxLength": 120 + }, + "website": { + "type": "string", + "format": "uri", + "pattern": "^https://", + "maxLength": 2048 + }, + "supportEmail": { + "type": "string", + "format": "email", + "maxLength": 320 + } + }, + "required": [ + "name", + "website", + "supportEmail" + ] + } + }, + "required": [ + "business" + ] + }, + "ProductionEnrollmentResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "$ref": "#/components/schemas/ProjectId" + }, + "orgId": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "stage": { + "type": "string", + "enum": [ + "development" + ] + }, + "operationId": { + "type": "string", + "format": "uuid" + }, + "enrollmentStatus": { + "type": "string", + "enum": [ + "requested", + "approval_required", + "provisioning", + "ready" + ] + } + }, + "required": [ + "id", + "orgId", + "name", + "slug", + "stage", + "operationId", + "enrollmentStatus" + ] + }, + "ProductionEnrollmentCommandResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "action": { + "type": "string", + "enum": [ + "approve", + "cancel" + ] + }, + "accepted": { + "type": "boolean", + "enum": [ + true + ] + } + }, + "required": [ + "operationId", + "action", + "accepted" + ] + }, + "CursorPageMetadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "nextCursor": { + "type": "string", + "nullable": true + }, + "hasMore": { + "type": "boolean" + } + }, + "required": [ + "nextCursor", + "hasMore" + ] + }, + "BanSafeHealthProbabilities": { + "type": "object", + "additionalProperties": false, + "properties": { + "healthy": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "limited": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "restricted": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "banned": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "healthy", + "limited", + "restricted", + "banned" + ] + }, + "BanSafeObservedAccountState": { + "type": "object", + "additionalProperties": false, + "description": "Direct account-state evidence. This is not an ML estimate.", + "properties": { + "state": { + "type": "string", + "enum": [ + "healthy", + "limited", + "restricted", + "banned" + ] + }, + "observedAt": { + "type": "string", + "format": "date-time" + }, + "source": { + "type": "string", + "enum": [ + "account_check", + "restriction_event" + ] + } + }, + "required": [ + "state", + "observedAt", + "source" + ] + }, + "BanSafeHealthExplanationFactor": { + "type": "object", + "additionalProperties": false, + "description": "One factual rules-v1 input. penalty is the number of Health points this input subtracts.", + "properties": { + "group": { + "type": "string", + "enum": [ + "direct_condition", + "delivery", + "connection", + "conduct", + "cadence" + ] + }, + "key": { + "type": "string", + "enum": [ + "observed_limited", + "observed_restricted", + "observed_banned", + "send_failures", + "receipt_errors", + "server_ack_tail", + "connection_failures", + "connection_churn", + "connection_disconnected", + "auto_reconnect_errors", + "keep_alive_errors", + "unanswered_first_contacts", + "unsolicited_sends", + "send_burst", + "fixed_send_rhythm" + ] + }, + "penalty": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "observedValue": { + "type": "number" + }, + "sampleSize": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "group", + "key", + "penalty", + "observedValue", + "sampleSize" + ] + }, + "BanSafeHealthExplanation": { + "type": "object", + "additionalProperties": false, + "description": "Bounded rules-v1 inputs and deductions. It is not a forecast or confidence score.", + "properties": { + "penalties": { + "type": "object", + "additionalProperties": false, + "properties": { + "conduct": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "delivery": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "connection": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "restriction": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "total": { + "type": "number", + "minimum": 0, + "maximum": 100 + } + }, + "required": [ + "conduct", + "delivery", + "connection", + "restriction", + "total" + ] + }, + "factors": { + "type": "array", + "maxItems": 8, + "items": { + "$ref": "#/components/schemas/BanSafeHealthExplanationFactor" + } + }, + "measuredGroups": { + "type": "array", + "maxItems": 5, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "direct_condition", + "delivery", + "connection", + "conduct", + "cadence" + ] + } + }, + "missingGroups": { + "type": "array", + "maxItems": 5, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "direct_condition", + "delivery", + "connection", + "conduct", + "cadence" + ] + } + } + }, + "required": [ + "penalties", + "factors", + "measuredGroups", + "missingGroups" + ] + }, + "BanSafeSignalDefinition": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "number", + "boolean", + "enum", + "histogram", + "code_counts" + ] + }, + "unit": { + "type": "string", + "enum": [ + "count", + "milliseconds", + "unix_milliseconds", + "ratio", + "none" + ] + }, + "description": { + "type": "string" + } + }, + "required": [ + "key", + "label", + "group", + "kind", + "unit", + "description" + ] + }, + "BanSafeSignalCodeCount": { + "type": "object", + "additionalProperties": false, + "properties": { + "code": { + "type": "integer", + "minimum": 0 + }, + "count": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "code", + "count" + ] + }, + "BanSafeSignal": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "type": "string" + }, + "label": { + "type": "string" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string", + "enum": [ + "number", + "boolean", + "enum", + "histogram", + "code_counts" + ] + }, + "unit": { + "type": "string", + "enum": [ + "count", + "milliseconds", + "unix_milliseconds", + "ratio", + "none" + ] + }, + "description": { + "type": "string" + }, + "measured": { + "type": "boolean" + }, + "value": { + "nullable": true, + "oneOf": [ + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "number" + } + } + ] + }, + "sampleSize": { + "type": "integer", + "minimum": 0, + "nullable": true + }, + "codes": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/BanSafeSignalCodeCount" + } + } + }, + "required": [ + "key", + "label", + "group", + "kind", + "unit", + "description", + "measured", + "value", + "sampleSize", + "codes" + ] + }, + "BanSafeCollectionStatus": { + "type": "object", + "additionalProperties": false, + "properties": { + "state": { + "type": "string", + "enum": [ + "fresh", + "stale", + "not_collected", + "unsupported" + ] + }, + "latestFlushedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "latestReceivedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "freshUntil": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "recordVersion": { + "type": "integer", + "minimum": 0, + "nullable": true + }, + "collectorVersion": { + "type": "integer", + "minimum": 0, + "nullable": true + }, + "partial": { + "type": "boolean", + "nullable": true + }, + "droppedRecords": { + "type": "integer", + "minimum": 0, + "nullable": true + } + }, + "required": [ + "state", + "latestFlushedAt", + "latestReceivedAt", + "freshUntil", + "recordVersion", + "collectorVersion", + "partial", + "droppedRecords" + ] + }, + "BanSafeTelemetrySnapshot": { + "type": "object", + "additionalProperties": false, + "properties": { + "bucketStart": { + "type": "string", + "format": "date-time" + }, + "flushedAt": { + "type": "string", + "format": "date-time" + }, + "receivedAt": { + "type": "string", + "format": "date-time" + }, + "partial": { + "type": "boolean" + }, + "recordVersion": { + "type": "integer", + "minimum": 0, + "nullable": true + }, + "signals": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeSignal" + } + } + }, + "required": [ + "bucketStart", + "flushedAt", + "receivedAt", + "partial", + "recordVersion", + "signals" + ] + }, + "BanSafeCollectionSession": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "collection": { + "$ref": "#/components/schemas/BanSafeCollectionStatus" + } + }, + "required": [ + "sessionId", + "session", + "projectId", + "collection" + ] + }, + "BanSafeTelemetryDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "collection": { + "$ref": "#/components/schemas/BanSafeCollectionStatus" + }, + "snapshot": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeTelemetrySnapshot" + } + ] + } + }, + "required": [ + "sessionId", + "session", + "projectId", + "collection", + "snapshot" + ] + }, + "BanSafeHealthAction": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "mode": { + "type": "string", + "enum": [ + "apply", + "clear" + ] + }, + "action": { + "type": "string", + "enum": [ + "stop", + "slow_down", + "log_out", + "email", + "webhook" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "succeeded", + "failed", + "cancelled" + ] + }, + "health": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "threshold": { + "type": "number", + "minimum": 0, + "maximum": 100 + }, + "healthSource": { + "type": "string", + "enum": [ + "rules_v1", + "ml_model" + ] + }, + "estimatorVersion": { + "type": "string" + }, + "modelVersion": { + "type": "string", + "nullable": true + }, + "slowDownMps": { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true, + "nullable": true + }, + "evaluatedAt": { + "type": "string", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "outcome": { + "type": "string", + "nullable": true, + "enum": [ + "applied", + "cleared", + "notification_queued", + "superseded", + "expired", + "not_applied", + "delivery_failed", + null + ] + } + }, + "required": [ + "id", + "sessionId", + "session", + "projectId", + "mode", + "action", + "status", + "health", + "threshold", + "healthSource", + "estimatorVersion", + "modelVersion", + "slowDownMps", + "evaluatedAt", + "createdAt", + "completedAt", + "outcome" + ] + }, + "BanSafeNumberEnforcement": { + "type": "object", + "additionalProperties": false, + "properties": { + "rung": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + }, + "previousRung": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + }, + "organizationFloor": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ], + "description": "The lowest restriction every number in this workspace is held to." + }, + "reason": { + "type": "string" + }, + "source": { + "type": "string", + "enum": [ + "automatic", + "operator" + ] + }, + "throughputPerMinute": { + "type": "number", + "nullable": true, + "description": "Messages per minute this number is paced to, or null when it is not paced." + }, + "blocksUnsolicited": { + "type": "boolean", + "description": "First messages to people who never wrote to this number are refused outside Campaigns." + }, + "suspended": { + "type": "boolean", + "description": "This number cannot originate a message. It still receives, reads, and shows presence." + }, + "startedAt": { + "type": "string", + "format": "date-time" + }, + "eligibleLiftAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "exitProgress": { + "type": "integer", + "minimum": 0, + "description": "Consecutive checks already passed toward lifting." + }, + "blockingFindings": { + "type": "array", + "items": { + "type": "string" + } + }, + "operatorHold": { + "type": "boolean" + }, + "appealState": { + "type": "string", + "enum": [ + "none", + "requested", + "granted", + "denied" + ] + }, + "state": { + "type": "string", + "enum": [ + "applied", + "applying" + ], + "description": "`applying` while the number has not confirmed the restriction." + } + }, + "required": [ + "rung", + "previousRung", + "organizationFloor", + "reason", + "source", + "throughputPerMinute", + "blocksUnsolicited", + "suspended", + "startedAt", + "eligibleLiftAt", + "exitProgress", + "blockingFindings", + "operatorHold", + "appealState", + "state" + ] + }, + "BanSafeNumber": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "health": { + "type": "number", + "minimum": 0, + "maximum": 100, + "nullable": true, + "description": "Estimate of present account Health. Higher is healthier. Read healthSource, healthReliability, and healthFeatureCoverage with it." + }, + "band": { + "type": "string", + "enum": [ + "good", + "fair", + "poor", + "failing", + "unknown" + ] + }, + "healthSource": { + "type": "string", + "enum": [ + "rules_v1", + "ml_model", + "unavailable" + ], + "description": "Estimator family. rules_v1 is deterministic; unavailable carries no numeric Health." + }, + "healthEstimatorVersion": { + "type": "string", + "nullable": true, + "description": "Version of the estimator that produced Health." + }, + "healthModelVersion": { + "type": "string", + "nullable": true, + "description": "Learned-model artifact version. Null for rules_v1." + }, + "healthEvaluatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "healthFeatureCoverage": { + "type": "number", + "minimum": 0, + "maximum": 1, + "nullable": true + }, + "healthReliability": { + "type": "string", + "enum": [ + "rules_based", + "validated", + "unavailable" + ], + "description": "Support category, not a confidence score." + }, + "healthUnavailableReason": { + "type": "string", + "nullable": true, + "enum": [ + "no_active_model", + "invalid_active_model", + "insufficient_fresh_features", + null + ] + }, + "healthProbabilities": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthProbabilities" + } + ] + }, + "mostLikelyHealthState": { + "type": "string", + "enum": [ + "healthy", + "limited", + "restricted", + "banned", + null + ], + "nullable": true + }, + "healthExplanation": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthExplanation" + } + ] + }, + "observedAccountState": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeObservedAccountState" + } + ] + }, + "enforcement": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeNumberEnforcement" + } + ] + } + }, + "required": [ + "sessionId", + "session", + "phoneNumber", + "projectId", + "health", + "band", + "healthSource", + "healthEstimatorVersion", + "healthModelVersion", + "healthEvaluatedAt", + "healthFeatureCoverage", + "healthReliability", + "healthUnavailableReason", + "healthProbabilities", + "mostLikelyHealthState", + "healthExplanation", + "observedAccountState", + "enforcement" + ] + }, + "BanSafeFinding": { + "type": "object", + "additionalProperties": false, + "description": "One safety finding, with the sentences to show a customer. A `not_measured` entry has no stored lifecycle and reports null timestamps; it is never reported as resolved and never omitted.", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "key": { + "type": "string", + "maxLength": 64 + }, + "title": { + "type": "string", + "description": "Customer-visible name of the check. A `not_measured` entry carries the same title as a stored one." + }, + "summary": { + "type": "string", + "description": "The evidence sentence for this finding, with the numbers from `evidence` already filled in. A number the check could not read reads as `unknown`, and a `not_measured` entry therefore reads as the sentence with no numbers in it. Empty for a key Polymorfa has retired." + }, + "fix": { + "type": "string", + "description": "What to change to clear the finding. Empty for a key Polymorfa has retired." + }, + "status": { + "type": "string", + "enum": [ + "open", + "acknowledged", + "resolved", + "not_measured" + ] + }, + "severity": { + "type": "string", + "enum": [ + "info", + "warning", + "critical", + null + ], + "nullable": true + }, + "occurrences": { + "type": "integer", + "minimum": 0 + }, + "reopenedCount": { + "type": "integer", + "minimum": 0 + }, + "evidence": { + "type": "object", + "additionalProperties": true, + "description": "Numbers only. Never message content, a message identifier, or a recipient identifier." + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "firstSeenAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "lastSeenAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "acknowledgedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "acknowledgedBy": { + "type": "string", + "nullable": true + }, + "acknowledgementNote": { + "type": "string", + "nullable": true, + "maxLength": 500 + }, + "snoozedUntil": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "resolvedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "resolveReason": { + "type": "string", + "nullable": true, + "enum": [ + "clean", + "key_retired", + "number_removed", + "stale", + null + ] + } + }, + "required": [ + "id", + "key", + "title", + "summary", + "fix", + "status", + "severity", + "occurrences", + "reopenedCount", + "evidence", + "sessionId", + "session", + "phoneNumber", + "firstSeenAt", + "lastSeenAt", + "acknowledgedAt", + "acknowledgedBy", + "acknowledgementNote", + "snoozedUntil", + "resolvedAt", + "resolveReason" + ] + }, + "BanSafeNumberDetail": { + "type": "object", + "additionalProperties": false, + "properties": { + "health": { + "type": "number", + "minimum": 0, + "maximum": 100, + "nullable": true, + "description": "Estimate of present account Health. Higher is healthier. Read healthSource, healthReliability, and healthFeatureCoverage with it." + }, + "band": { + "type": "string", + "enum": [ + "good", + "fair", + "poor", + "failing", + "unknown" + ] + }, + "healthSource": { + "type": "string", + "enum": [ + "rules_v1", + "ml_model", + "unavailable" + ], + "description": "Estimator family. rules_v1 is deterministic; unavailable carries no numeric Health." + }, + "healthEstimatorVersion": { + "type": "string", + "nullable": true, + "description": "Version of the estimator that produced Health." + }, + "healthModelVersion": { + "type": "string", + "nullable": true, + "description": "Learned-model artifact version. Null for rules_v1." + }, + "healthEvaluatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "healthFeatureCoverage": { + "type": "number", + "minimum": 0, + "maximum": 1, + "nullable": true + }, + "healthReliability": { + "type": "string", + "enum": [ + "rules_based", + "validated", + "unavailable" + ], + "description": "Support category, not a confidence score." + }, + "healthUnavailableReason": { + "type": "string", + "nullable": true, + "enum": [ + "no_active_model", + "invalid_active_model", + "insufficient_fresh_features", + null + ] + }, + "healthProbabilities": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthProbabilities" + } + ] + }, + "mostLikelyHealthState": { + "type": "string", + "enum": [ + "healthy", + "limited", + "restricted", + "banned", + null + ], + "nullable": true + }, + "healthExplanation": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthExplanation" + } + ] + }, + "observedAccountState": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeObservedAccountState" + } + ] + }, + "warmup": { + "$ref": "#/components/schemas/BanSafeNumberWarmup" + }, + "findings": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeFinding" + } + }, + "liftRequires": { + "type": "string", + "nullable": true, + "description": "The exact remaining condition for the restriction to lift." + }, + "appealState": { + "type": "string", + "enum": [ + "none", + "requested", + "granted", + "denied" + ] + } + }, + "required": [ + "sessionId", + "session", + "phoneNumber", + "projectId", + "health", + "band", + "healthSource", + "healthEstimatorVersion", + "healthModelVersion", + "healthEvaluatedAt", + "healthFeatureCoverage", + "healthReliability", + "healthUnavailableReason", + "healthProbabilities", + "mostLikelyHealthState", + "healthExplanation", + "observedAccountState", + "enforcement", + "warmup", + "findings", + "liftRequires", + "appealState" + ] + }, + "BanSafeNumberWarmup": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + }, + "tenureSource": { + "type": "string", + "enum": [ + "history", + "link", + "plan", + null + ], + "nullable": true, + "description": "Retained evidence anchoring the ramp; null when legacy evidence cannot be classified." + }, + "tenureDay": { + "type": "integer", + "minimum": 0, + "description": "Whole days since the number's known tenure lower bound; zero when unknown." + }, + "allowance": { + "type": "integer", + "minimum": 0, + "nullable": true, + "description": "Messages allowed today; null when the plan is disabled." + }, + "sentToday": { + "type": "integer", + "minimum": 0, + "nullable": true, + "description": "Durable reservations in the active allowance window. Successful current reads return 0 before the first reservation; null remains accepted for older stored responses." + }, + "resetsAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "curve": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WarmupCurvePoint" + } + } + }, + "required": [ + "enabled", + "tenureSource", + "tenureDay", + "allowance", + "sentToday", + "resetsAt", + "curve" + ] + }, + "ProjectInsuranceEvidence": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "enabled": { + "type": "boolean" + }, + "banInsuranceIncluded": { + "type": "boolean" + } + }, + "required": [ + "projectId", + "enabled", + "banInsuranceIncluded" + ] + }, + "UpdateProjectInsuranceEvidenceInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ] + }, + "BanSafeHealthPoint": { + "type": "object", + "additionalProperties": false, + "properties": { + "health": { + "type": "number", + "minimum": 0, + "maximum": 100, + "nullable": true + }, + "band": { + "type": "string", + "enum": [ + "good", + "fair", + "poor", + "failing", + "unknown", + null + ], + "nullable": true + }, + "healthSource": { + "type": "string", + "enum": [ + "rules_v1", + "ml_model", + "unavailable" + ] + }, + "healthEstimatorVersion": { + "type": "string", + "nullable": true + }, + "healthModelVersion": { + "type": "string", + "nullable": true + }, + "healthEvaluatedAt": { + "type": "string", + "format": "date-time" + }, + "healthFeatureCoverage": { + "type": "number", + "minimum": 0, + "maximum": 1, + "nullable": true + }, + "healthReliability": { + "type": "string", + "enum": [ + "rules_based", + "validated", + "unavailable" + ] + }, + "healthUnavailableReason": { + "type": "string", + "nullable": true, + "enum": [ + "no_active_model", + "invalid_active_model", + "insufficient_fresh_features", + null + ] + }, + "healthProbabilities": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthProbabilities" + } + ] + }, + "mostLikelyHealthState": { + "type": "string", + "enum": [ + "healthy", + "limited", + "restricted", + "banned", + null + ], + "nullable": true + }, + "healthExplanation": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthExplanation" + } + ] + }, + "observedAccountState": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeObservedAccountState" + } + ] + } + }, + "required": [ + "health", + "band", + "healthSource", + "healthEstimatorVersion", + "healthModelVersion", + "healthEvaluatedAt", + "healthFeatureCoverage", + "healthReliability", + "healthUnavailableReason", + "healthProbabilities", + "mostLikelyHealthState", + "healthExplanation", + "observedAccountState" + ] + }, + "BanSafeHealthHistory": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "points": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BanSafeHealthPoint" + } + } + }, + "required": [ + "sessionId", + "session", + "points" + ] + }, + "BanSafeFindingAcknowledgement": { + "type": "object", + "additionalProperties": false, + "properties": { + "finding": { + "$ref": "#/components/schemas/BanSafeFinding" + }, + "message": { + "type": "string", + "description": "The exact sentence shown in the console next to the button." + } + }, + "required": [ + "finding", + "message" + ] + }, + "BanSafeEnforcementSummary": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "rung": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + }, + "previousRung": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + }, + "organizationFloor": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + }, + "reason": { + "type": "string" + }, + "source": { + "type": "string", + "enum": [ + "automatic", + "operator" + ] + }, + "throughputPerMinute": { + "type": "number", + "nullable": true + }, + "blocksUnsolicited": { + "type": "boolean" + }, + "suspended": { + "type": "boolean" + }, + "health": { + "type": "number", + "minimum": 0, + "maximum": 100, + "nullable": true, + "description": "Estimate of present account Health. Higher is healthier. Read healthSource, healthReliability, and healthFeatureCoverage with it." + }, + "band": { + "type": "string", + "enum": [ + "good", + "fair", + "poor", + "failing", + "unknown" + ] + }, + "healthSource": { + "type": "string", + "enum": [ + "rules_v1", + "ml_model", + "unavailable" + ], + "description": "Estimator family. rules_v1 is deterministic; unavailable carries no numeric Health." + }, + "healthEstimatorVersion": { + "type": "string", + "nullable": true, + "description": "Version of the estimator that produced Health." + }, + "healthModelVersion": { + "type": "string", + "nullable": true, + "description": "Learned-model artifact version. Null for rules_v1." + }, + "healthEvaluatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "healthFeatureCoverage": { + "type": "number", + "minimum": 0, + "maximum": 1, + "nullable": true + }, + "healthReliability": { + "type": "string", + "enum": [ + "rules_based", + "validated", + "unavailable" + ], + "description": "Support category, not a confidence score." + }, + "healthUnavailableReason": { + "type": "string", + "nullable": true, + "enum": [ + "no_active_model", + "invalid_active_model", + "insufficient_fresh_features", + null + ] + }, + "healthProbabilities": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthProbabilities" + } + ] + }, + "mostLikelyHealthState": { + "type": "string", + "enum": [ + "healthy", + "limited", + "restricted", + "banned", + null + ], + "nullable": true + }, + "healthExplanation": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeHealthExplanation" + } + ] + }, + "observedAccountState": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeObservedAccountState" + } + ] + }, + "enforcement": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/BanSafeNumberEnforcement" + } + ] + }, + "blockingFindings": { + "type": "array", + "items": { + "type": "string" + } + }, + "startedAt": { + "type": "string", + "format": "date-time" + }, + "eligibleLiftAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "liftRequires": { + "type": "string" + }, + "operatorHold": { + "type": "boolean" + }, + "appealState": { + "type": "string", + "enum": [ + "none", + "requested", + "granted", + "denied" + ] + }, + "state": { + "type": "string", + "enum": [ + "applied", + "applying" + ] + } + }, + "required": [ + "sessionId", + "session", + "phoneNumber", + "projectId", + "rung", + "previousRung", + "organizationFloor", + "reason", + "source", + "throughputPerMinute", + "blocksUnsolicited", + "suspended", + "health", + "band", + "healthSource", + "healthEstimatorVersion", + "healthModelVersion", + "healthEvaluatedAt", + "healthFeatureCoverage", + "healthReliability", + "healthUnavailableReason", + "healthProbabilities", + "mostLikelyHealthState", + "healthExplanation", + "observedAccountState", + "blockingFindings", + "startedAt", + "eligibleLiftAt", + "liftRequires", + "operatorHold", + "appealState", + "state" + ] + }, + "BanSafeAppealReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "rung": { + "type": "string", + "enum": [ + "none", + "notify", + "throttle", + "block_cold", + "suspend" + ] + }, + "appealState": { + "type": "string", + "enum": [ + "none", + "requested", + "granted", + "denied" + ] + }, + "requestedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "liftRequires": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "sessionId", + "session", + "rung", + "appealState", + "requestedAt", + "liftRequires", + "message" + ] + }, + "BanSafeIncident": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "kind": { + "type": "string", + "enum": [ + "cap_warning", + "cap_reached", + "timelock", + "temporary_ban", + "permanent_ban", + "connect_blocked", + "customer_report" + ] + }, + "source": { + "type": "string", + "enum": [ + "runtime", + "customer" + ] + }, + "resolution": { + "type": "string" + }, + "ambiguous": { + "type": "boolean" + }, + "startedAt": { + "type": "string", + "format": "date-time" + }, + "endsAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "closedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "closedBy": { + "type": "string", + "nullable": true + }, + "claimId": { + "type": "string", + "format": "uuid", + "nullable": true + }, + "note": { + "type": "string", + "nullable": true, + "maxLength": 500 + }, + "reportedBy": { + "type": "string", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "sessionId", + "session", + "phoneNumber", + "projectId", + "kind", + "source", + "resolution", + "ambiguous", + "startedAt", + "endsAt", + "note", + "reportedBy", + "createdAt", + "closedAt", + "closedBy", + "claimId" + ] + }, + "BanSafeIncidentReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "incidentId": { + "type": "string", + "format": "uuid" + }, + "created": { + "type": "boolean", + "description": "False when the same Idempotency-Key already recorded this report." + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "incidentId", + "created", + "sessionId", + "session", + "occurredAt" + ] + }, + "BanSafeClaimEvidence": { + "type": "object", + "additionalProperties": false, + "description": "Counts behind the attribution. Never a recipient, a message, or a device model.", + "properties": { + "attributionRuleVersion": { + "type": "integer", + "minimum": 1, + "nullable": true, + "description": "Attribution rules used when the claim was filed. Null for claims filed before rule versioning." + }, + "windowDays": { + "type": "integer", + "minimum": 1 + }, + "deviceEvidence": { + "type": "boolean", + "description": "Whether ban insurance evidence collection is on for the project." + }, + "otherDevices": { + "type": "integer", + "minimum": 0 + }, + "restrictedInWindow": { + "type": "boolean", + "description": "Whether Polymorfa was restricting this number's sending inside the window." + }, + "criticalFindingDays": { + "type": "integer", + "minimum": 0, + "description": "Days one safety check stayed at its most serious level inside the window." + }, + "sharedConnection": { + "type": "boolean", + "description": "Whether this number shared its connection with numbers that were being restricted." + }, + "measuredHours": { + "type": "integer", + "minimum": 0, + "description": "Hours of measured activity Polymorfa holds for the window." + } + }, + "required": [ + "attributionRuleVersion", + "windowDays", + "deviceEvidence", + "otherDevices", + "restrictedInWindow", + "criticalFindingDays", + "sharedConnection", + "measuredHours" + ] + }, + "BanSafeClaim": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "incidentId": { + "type": "string", + "format": "uuid" + }, + "sessionId": { + "type": "string", + "format": "uuid" + }, + "session": { + "type": "string" + }, + "phoneNumber": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string", + "enum": [ + "filed", + "under_review", + "approved", + "denied", + "paid", + "reversed" + ] + }, + "verdict": { + "type": "string", + "enum": [ + "other_device", + "customer_conduct", + "shared_network", + "ours", + "inconclusive" + ] + }, + "windowStart": { + "type": "string", + "format": "date-time" + }, + "windowEnd": { + "type": "string", + "format": "date-time" + }, + "measuredCents": { + "type": "integer", + "minimum": 0, + "description": "Credits this number consumed inside the window, in cents." + }, + "capCents": { + "type": "integer", + "minimum": 0, + "description": "The most a claim on this number's plan can return, in cents." + }, + "amountCents": { + "type": "integer", + "minimum": 0, + "description": "What this claim returns, in cents." + }, + "evidence": { + "$ref": "#/components/schemas/BanSafeClaimEvidence" + }, + "summary": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "decidedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "paidAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "incidentId", + "sessionId", + "session", + "phoneNumber", + "projectId", + "status", + "verdict", + "windowStart", + "windowEnd", + "measuredCents", + "capCents", + "amountCents", + "evidence", + "summary", + "reason", + "decidedAt", + "paidAt", + "createdAt" + ] + }, + "AcknowledgeBanSafeFindingInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "note": { + "type": "string", + "maxLength": 500 + }, + "snoozeDays": { + "type": "integer", + "minimum": 1, + "maximum": 30, + "description": "Silence this finding's notifications for this many days." + } + } + }, + "AppealBanSafeEnforcementInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "note": { + "type": "string", + "minLength": 1, + "maxLength": 1000 + } + }, + "required": [ + "note" + ] + }, + "ReportBanSafeIncidentInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "session": { + "type": "string", + "minLength": 1, + "maxLength": 256 + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "note": { + "type": "string", + "maxLength": 500 + } + }, + "required": [ + "session" + ] + }, + "SafeModeSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "presence": { + "type": "string", + "enum": [ + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "off", + "jittered", + "conversation" + ] + }, + "onlineStart": { + "type": "integer", + "minimum": 0, + "maximum": 23 + }, + "onlineEnd": { + "type": "integer", + "minimum": 0, + "maximum": 23 + } + }, + "required": [ + "presence", + "typing", + "reads", + "pacing", + "onlineStart", + "onlineEnd" + ] + }, + "SafeModeOverride": { + "type": "object", + "additionalProperties": false, + "properties": { + "presence": { + "type": "string", + "enum": [ + "inherit", + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "inherit", + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "inherit", + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "inherit", + "off", + "jittered", + "conversation" + ] + } + }, + "required": [ + "presence", + "typing", + "reads", + "pacing" + ] + }, + "SafeModeApplied": { + "type": "object", + "additionalProperties": false, + "description": "What the number itself last reported it is running. An observation, not a claim.", + "properties": { + "observedAt": { + "type": "string", + "format": "date-time" + }, + "presence": { + "type": "string", + "nullable": true + }, + "typing": { + "type": "string", + "nullable": true + }, + "reads": { + "type": "string", + "nullable": true + }, + "pacing": { + "type": "string", + "nullable": true + } + }, + "required": [ + "observedAt", + "presence", + "typing", + "reads", + "pacing" + ] + }, + "ProjectSafeMode": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "ceiling": { + "$ref": "#/components/schemas/SafeModeSettings" + }, + "entitled": { + "type": "boolean", + "description": "Whether this project's plan includes BanSafe Lite, which Safe Mode is part of. When false, a request that raises a setting is refused." + }, + "entitlementReason": { + "type": "string", + "nullable": true, + "description": "Why a raise would be refused. Null when the plan includes BanSafe Lite." + } + }, + "required": [ + "projectId", + "ceiling", + "entitled", + "entitlementReason" + ] + }, + "SessionSafeMode": { + "type": "object", + "additionalProperties": false, + "properties": { + "session": { + "type": "string" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "project": { + "$ref": "#/components/schemas/SafeModeSettings" + }, + "override": { + "$ref": "#/components/schemas/SafeModeOverride" + }, + "effective": { + "$ref": "#/components/schemas/SafeModeSettings" + }, + "applied": { + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/SafeModeApplied" + } + ], + "nullable": true + }, + "mismatch": { + "type": "boolean", + "description": "True when the number reports something other than the policy in force." + }, + "entitled": { + "type": "boolean", + "description": "Whether this number's plan includes BanSafe Lite, which Safe Mode is part of. When false, a request that raises a setting is refused." + }, + "entitlementReason": { + "type": "string", + "nullable": true, + "description": "Why a raise would be refused. Null when the plan includes BanSafe Lite." + } + }, + "required": [ + "session", + "projectId", + "project", + "override", + "effective", + "applied", + "mismatch", + "entitled", + "entitlementReason" + ] + }, + "UpdateProjectSafeModeInput": { + "type": "object", + "additionalProperties": false, + "description": "A partial update: send only the settings you want to change.", + "properties": { + "presence": { + "type": "string", + "enum": [ + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "off", + "jittered", + "conversation" + ] + }, + "onlineStart": { + "type": "integer", + "minimum": 0, + "maximum": 23 + }, + "onlineEnd": { + "type": "integer", + "minimum": 0, + "maximum": 23 + } + } + }, + "UpdateSessionSafeModeInput": { + "type": "object", + "additionalProperties": false, + "description": "A partial update. `inherit` follows the project ceiling.", + "properties": { + "presence": { + "type": "string", + "enum": [ + "inherit", + "dark", + "online_while_sending", + "online_hours" + ] + }, + "typing": { + "type": "string", + "enum": [ + "inherit", + "off", + "before_text", + "before_all" + ] + }, + "reads": { + "type": "string", + "enum": [ + "inherit", + "off", + "replied_chats", + "all_inbound" + ] + }, + "pacing": { + "type": "string", + "enum": [ + "inherit", + "off", + "jittered", + "conversation" + ] + } + } + }, + "WarmupPlanSettings": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether every number in this project has a daily allowance." + }, + "warmupDays": { + "type": "integer", + "minimum": 1, + "maximum": 90, + "description": "Days the ramp takes to reach the per-number daily cap." + }, + "dailyStart": { + "type": "integer", + "minimum": 1, + "maximum": 2000, + "description": "Messages a number may send on its first day." + } + }, + "required": [ + "enabled", + "warmupDays", + "dailyStart" + ] + }, + "WarmupCurvePoint": { + "type": "object", + "additionalProperties": false, + "properties": { + "day": { + "type": "integer", + "minimum": 0, + "description": "Days since the number's first proven activity." + }, + "allowance": { + "type": "integer", + "minimum": 0, + "description": "Messages allowed on that day." + } + }, + "required": [ + "day", + "allowance" + ] + }, + "ProjectWarmupPlan": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "plan": { + "$ref": "#/components/schemas/WarmupPlanSettings" + }, + "ceiling": { + "type": "integer", + "minimum": 1, + "description": "The per-number daily cap the ramp climbs to." + }, + "curve": { + "type": "array", + "maxItems": 91, + "items": { + "$ref": "#/components/schemas/WarmupCurvePoint" + }, + "description": "The projected allowance day by day for a number whose health is good. A number in a lower health band gets less." + }, + "entitled": { + "type": "boolean", + "description": "Whether this project's plan includes BanSafe Lite, which the warm-up plan is part of. When false, turning the warm-up plan on is refused." + }, + "entitlementReason": { + "type": "string", + "nullable": true, + "description": "Why turning the plan on would be refused. Null when the plan includes BanSafe Lite." + } + }, + "required": [ + "projectId", + "plan", + "ceiling", + "curve", + "entitled", + "entitlementReason" + ] + }, + "UpdateProjectWarmupPlanInput": { + "type": "object", + "additionalProperties": false, + "description": "A partial update: send only the settings you want to change.", + "properties": { + "enabled": { + "type": "boolean" + }, + "warmupDays": { + "type": "integer", + "minimum": 1, + "maximum": 90 + }, + "dailyStart": { + "type": "integer", + "minimum": 1, + "maximum": 2000 + } + } + }, + "ProjectHealthPolicyIntegrations": { + "type": "object", + "additionalProperties": false, + "properties": { + "emailConfigured": { + "type": "boolean", + "description": "Whether notification email delivery is configured." + }, + "webhookConfigured": { + "type": "boolean", + "description": "Whether an enabled webhook exists for this organization or project." + } + }, + "required": [ + "emailConfigured", + "webhookConfigured" + ] + }, + "ProjectHealthPolicy": { + "type": "object", + "additionalProperties": false, + "properties": { + "projectId": { + "type": "string", + "format": "uuid" + }, + "version": { + "type": "integer", + "minimum": 0, + "description": "Revision required by the next update." + }, + "enabled": { + "type": "boolean" + }, + "threshold": { + "type": "integer", + "minimum": 0, + "maximum": 100, + "description": "Actions trigger only when an available health estimate is below this value." + }, + "sessionAction": { + "type": "string", + "enum": [ + "none", + "stop", + "slow_down", + "log_out" + ] + }, + "slowDownMps": { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true, + "nullable": true + }, + "emailNotification": { + "type": "boolean" + }, + "webhookNotification": { + "type": "boolean" + }, + "integrations": { + "$ref": "#/components/schemas/ProjectHealthPolicyIntegrations" + } + }, + "required": [ + "projectId", + "version", + "enabled", + "threshold", + "sessionAction", + "slowDownMps", + "emailNotification", + "webhookNotification", + "integrations" + ] + }, + "UpdateProjectHealthPolicyInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "version": { + "type": "integer", + "minimum": 0 + }, + "enabled": { + "type": "boolean" + }, + "threshold": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "sessionAction": { + "type": "string", + "enum": [ + "none", + "stop", + "slow_down", + "log_out" + ] + }, + "slowDownMps": { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true, + "nullable": true + }, + "emailNotification": { + "type": "boolean" + }, + "webhookNotification": { + "type": "boolean" + } + }, + "required": [ + "version", + "enabled", + "threshold", + "sessionAction", + "slowDownMps", + "emailNotification", + "webhookNotification" + ] + }, + "WebhookRetryPolicyInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "maximumAttempts": { + "type": "integer", + "minimum": 1, + "maximum": 10 + }, + "backoff": { + "type": "string", + "enum": [ + "constant", + "linear", + "exponential" + ] + }, + "initialDelaySeconds": { + "type": "integer", + "minimum": 1, + "maximum": 3600 + } + }, + "required": [ + "maximumAttempts", + "backoff", + "initialDelaySeconds" + ] + }, + "WebhookRetryPolicy": { + "type": "object", + "additionalProperties": false, + "properties": { + "maximumAttempts": { + "type": "integer", + "minimum": 1, + "maximum": 10 + }, + "backoff": { + "type": "string", + "enum": [ + "constant", + "linear", + "exponential" + ] + }, + "initialDelaySeconds": { + "type": "integer", + "minimum": 1, + "maximum": 3600 + } + }, + "required": [ + "maximumAttempts", + "backoff", + "initialDelaySeconds" + ] + }, + "WebhookHeaderInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$" + }, + "value": { + "type": "string", + "maxLength": 4096, + "pattern": "^(?![\\s\\S]*[\\u0000-\\u0008\\u000A-\\u001F\\u007F])[\\s\\S]*$", + "x-polymorfa-max-utf8-bytes": 4096, + "writeOnly": true, + "description": "Encrypted write-only HTTP field value. Limited to 4096 UTF-8 bytes. Line breaks, NUL, and other control characters except horizontal tab are rejected." + } + }, + "required": [ + "name", + "value" + ] + }, + "WebhookHeaderMetadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "required": [ + "name" + ] + }, + "WebhookSigningSecretMetadata": { + "type": "object", + "additionalProperties": false, + "properties": { + "version": { + "type": "integer", + "minimum": 1 + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "previousValidUntil": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "required": [ + "version", + "createdAt", + "previousValidUntil" + ] + }, + "CreateOrganizationWebhookInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string", + "format": "uri", + "minLength": 1, + "maxLength": 2048 + }, + "eventTypes": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "enabled": { + "type": "boolean", + "default": true + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ], + "default": "native" + }, + "retryPolicy": { + "$ref": "#/components/schemas/WebhookRetryPolicyInput" + }, + "headers": { + "type": "array", + "maxItems": 10, + "items": { + "$ref": "#/components/schemas/WebhookHeaderInput" + } + } + }, + "required": [ + "url", + "eventTypes" + ] + }, + "CreateProjectWebhookInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string", + "format": "uri", + "minLength": 1, + "maxLength": 2048 + }, + "eventTypes": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "enabled": { + "type": "boolean", + "default": true + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ], + "default": "native" + }, + "retryPolicy": { + "$ref": "#/components/schemas/WebhookRetryPolicyInput" + }, + "headers": { + "type": "array", + "maxItems": 10, + "items": { + "$ref": "#/components/schemas/WebhookHeaderInput" + } + } + }, + "required": [ + "url", + "eventTypes" + ] + }, + "UpdateOrganizationWebhookInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string", + "format": "uri", + "minLength": 1, + "maxLength": 2048 + }, + "eventTypes": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + }, + "retryPolicy": { + "$ref": "#/components/schemas/WebhookRetryPolicyInput" + }, + "headers": { + "type": "array", + "maxItems": 10, + "items": { + "$ref": "#/components/schemas/WebhookHeaderInput" + } + } + }, + "minProperties": 1 + }, + "UpdateProjectWebhookInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "url": { + "type": "string", + "format": "uri", + "minLength": 1, + "maxLength": 2048 + }, + "eventTypes": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + }, + "retryPolicy": { + "$ref": "#/components/schemas/WebhookRetryPolicyInput" + }, + "headers": { + "type": "array", + "maxItems": 10, + "items": { + "$ref": "#/components/schemas/WebhookHeaderInput" + } + } + }, + "minProperties": 1 + }, + "RotateWebhookSecretInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "overlapSeconds": { + "type": "integer", + "minimum": 0, + "maximum": 86400, + "default": 3600 + } + } + }, + "OrganizationWebhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "owner": { + "type": "string", + "enum": [ + "organization" + ] + }, + "projectId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "url": { + "type": "string", + "format": "uri", + "maxLength": 2048 + }, + "eventTypes": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + }, + "retryPolicy": { + "$ref": "#/components/schemas/WebhookRetryPolicy" + }, + "headers": { + "type": "array", + "maxItems": 10, + "items": { + "$ref": "#/components/schemas/WebhookHeaderMetadata" + } + }, + "secret": { + "$ref": "#/components/schemas/WebhookSigningSecretMetadata" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "organizationId", + "owner", + "projectId", + "url", + "eventTypes", + "enabled", + "format", + "retryPolicy", + "headers", + "secret", + "createdAt", + "updatedAt" + ] + }, + "ProjectWebhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "owner": { + "type": "string", + "enum": [ + "project" + ] + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "url": { + "type": "string", + "format": "uri", + "maxLength": 2048 + }, + "eventTypes": { + "type": "array", + "minItems": 1, + "maxItems": 100, + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "maxLength": 128 + } + }, + "enabled": { + "type": "boolean" + }, + "format": { + "type": "string", + "enum": [ + "native", + "meta" + ] + }, + "retryPolicy": { + "$ref": "#/components/schemas/WebhookRetryPolicy" + }, + "headers": { + "type": "array", + "maxItems": 10, + "items": { + "$ref": "#/components/schemas/WebhookHeaderMetadata" + } + }, + "secret": { + "$ref": "#/components/schemas/WebhookSigningSecretMetadata" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "organizationId", + "owner", + "projectId", + "url", + "eventTypes", + "enabled", + "format", + "retryPolicy", + "headers", + "secret", + "createdAt", + "updatedAt" + ] + }, + "OrganizationWebhookCreationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhook": { + "$ref": "#/components/schemas/OrganizationWebhook" + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "secret": { + "type": "string", + "nullable": true, + "writeOnly": true + }, + "secretAvailable": { + "type": "boolean" + } + }, + "required": [ + "webhook", + "operationId", + "idempotency", + "secret", + "secretAvailable" + ] + }, + "ProjectWebhookCreationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhook": { + "$ref": "#/components/schemas/ProjectWebhook" + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "secret": { + "type": "string", + "nullable": true, + "writeOnly": true + }, + "secretAvailable": { + "type": "boolean" + } + }, + "required": [ + "webhook", + "operationId", + "idempotency", + "secret", + "secretAvailable" + ] + }, + "OrganizationWebhookMutationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhook": { + "$ref": "#/components/schemas/OrganizationWebhook" + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "webhook", + "operationId", + "idempotency" + ] + }, + "ProjectWebhookMutationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhook": { + "$ref": "#/components/schemas/ProjectWebhook" + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "webhook", + "operationId", + "idempotency" + ] + }, + "OrganizationWebhookDeletionReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhookId": { + "type": "string", + "format": "uuid" + }, + "deleted": { + "type": "boolean", + "enum": [ + true + ] + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "webhookId", + "deleted", + "operationId", + "idempotency" + ] + }, + "ProjectWebhookDeletionReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhookId": { + "type": "string", + "format": "uuid" + }, + "deleted": { + "type": "boolean", + "enum": [ + true + ] + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "webhookId", + "deleted", + "operationId", + "idempotency" + ] + }, + "OrganizationWebhookSecretRotationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhookId": { + "type": "string", + "format": "uuid" + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "secret": { + "type": "string", + "nullable": true, + "writeOnly": true + }, + "secretAvailable": { + "type": "boolean" + }, + "secretMetadata": { + "$ref": "#/components/schemas/WebhookSigningSecretMetadata" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "webhookId", + "operationId", + "secret", + "secretAvailable", + "secretMetadata", + "idempotency" + ] + }, + "ProjectWebhookSecretRotationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhookId": { + "type": "string", + "format": "uuid" + }, + "operationId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "secret": { + "type": "string", + "nullable": true, + "writeOnly": true + }, + "secretAvailable": { + "type": "boolean" + }, + "secretMetadata": { + "$ref": "#/components/schemas/WebhookSigningSecretMetadata" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "webhookId", + "operationId", + "secret", + "secretAvailable", + "secretMetadata", + "idempotency" + ] + }, + "EncodedEventPayload": { + "type": "object", + "additionalProperties": false, + "properties": { + "encoding": { + "type": "string", + "enum": [ + "base64" + ] + }, + "contentType": { + "type": "string", + "enum": [ + "application/json" + ] + }, + "data": { + "type": "string", + "format": "byte", + "maxLength": 87384, + "description": "Canonical base64 for the complete native webhook body; decoded bytes are limited to 65,536 bytes." + } + }, + "required": [ + "encoding", + "contentType", + "data" + ] + }, + "PayloadAvailability": { + "type": "string", + "enum": [ + "available", + "not_retained", + "expired", + "redacted", + "unavailable" + ] + }, + "OrganizationEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "type": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "source": { + "type": "string", + "enum": [ + "runtime", + "platform", + "test" + ] + }, + "environment": { + "type": "string", + "enum": [ + "development", + "production" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "payloadAvailability": { + "type": "string", + "enum": [ + "available", + "not_retained", + "expired", + "redacted", + "unavailable" + ] + }, + "payload": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/EncodedEventPayload" + } + ] + }, + "replayableUntil": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "metadataExpiresAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "type", + "source", + "environment", + "createdAt", + "payloadAvailability", + "payload", + "replayableUntil", + "metadataExpiresAt" + ] + }, + "ProjectEvent": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "type": { + "type": "string", + "minLength": 1, + "maxLength": 128 + }, + "source": { + "type": "string", + "enum": [ + "runtime", + "platform", + "test" + ] + }, + "environment": { + "type": "string", + "enum": [ + "development", + "production" + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "payloadAvailability": { + "type": "string", + "enum": [ + "available", + "not_retained", + "expired", + "redacted", + "unavailable" + ] + }, + "payload": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/EncodedEventPayload" + } + ] + }, + "replayableUntil": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "metadataExpiresAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "type", + "source", + "environment", + "createdAt", + "payloadAvailability", + "payload", + "replayableUntil", + "metadataExpiresAt" + ] + }, + "OrganizationWebhookDelivery": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "eventId": { + "type": "string", + "format": "uuid" + }, + "webhookId": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "delivering", + "retrying", + "succeeded", + "failed" + ] + }, + "attemptCount": { + "type": "integer", + "minimum": 0 + }, + "capabilities": { + "type": "object", + "additionalProperties": false, + "properties": { + "retryable": { + "type": "boolean" + } + }, + "required": [ + "retryable" + ] + }, + "payloadAvailability": { + "type": "string", + "enum": [ + "available", + "not_retained", + "expired", + "redacted", + "unavailable" + ] + }, + "replayableUntil": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "metadataExpiresAt": { + "type": "string", + "format": "date-time" + }, + "nextAttemptAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "lastAttemptAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "lastOutcome": { + "type": "object", + "nullable": true, + "additionalProperties": false, + "properties": { + "statusCode": { + "type": "integer", + "minimum": 100, + "maximum": 599, + "nullable": true + }, + "errorCode": { + "type": "string", + "nullable": true + } + }, + "required": [ + "statusCode", + "errorCode" + ] + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "eventId", + "webhookId", + "status", + "attemptCount", + "capabilities", + "payloadAvailability", + "replayableUntil", + "metadataExpiresAt", + "nextAttemptAt", + "lastAttemptAt", + "completedAt", + "createdAt", + "updatedAt", + "lastOutcome" + ] + }, + "ProjectWebhookDelivery": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "eventId": { + "type": "string", + "format": "uuid" + }, + "webhookId": { + "type": "string", + "format": "uuid" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "delivering", + "retrying", + "succeeded", + "failed" + ] + }, + "attemptCount": { + "type": "integer", + "minimum": 0 + }, + "capabilities": { + "type": "object", + "additionalProperties": false, + "properties": { + "retryable": { + "type": "boolean" + } + }, + "required": [ + "retryable" + ] + }, + "payloadAvailability": { + "type": "string", + "enum": [ + "available", + "not_retained", + "expired", + "redacted", + "unavailable" + ] + }, + "replayableUntil": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "metadataExpiresAt": { + "type": "string", + "format": "date-time" + }, + "nextAttemptAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "lastAttemptAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "lastOutcome": { + "type": "object", + "nullable": true, + "additionalProperties": false, + "properties": { + "statusCode": { + "type": "integer", + "minimum": 100, + "maximum": 599, + "nullable": true + }, + "errorCode": { + "type": "string", + "nullable": true + } + }, + "required": [ + "statusCode", + "errorCode" + ] + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "eventId", + "webhookId", + "status", + "attemptCount", + "capabilities", + "payloadAvailability", + "replayableUntil", + "metadataExpiresAt", + "nextAttemptAt", + "lastAttemptAt", + "completedAt", + "createdAt", + "updatedAt", + "lastOutcome" + ] + }, + "OrganizationWebhookDeliveryAttempt": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "deliveryId": { + "type": "string", + "format": "uuid" + }, + "number": { + "type": "integer", + "minimum": 1 + }, + "status": { + "type": "string", + "enum": [ + "pending", + "delivering", + "succeeded", + "failed" + ] + }, + "startedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "nextRetryAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "durationMs": { + "type": "integer", + "minimum": 0, + "nullable": true + }, + "statusCode": { + "type": "integer", + "minimum": 100, + "maximum": 599, + "nullable": true + }, + "errorCode": { + "type": "string", + "nullable": true + }, + "metadataExpiresAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "deliveryId", + "number", + "status", + "startedAt", + "completedAt", + "nextRetryAt", + "durationMs", + "statusCode", + "errorCode", + "metadataExpiresAt" + ] + }, + "ProjectWebhookDeliveryAttempt": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + }, + "number": { + "type": "integer", + "minimum": 1 + }, + "status": { + "type": "string", + "enum": [ + "pending", + "delivering", + "succeeded", + "failed" + ] + }, + "startedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "nextRetryAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "durationMs": { + "type": "integer", + "minimum": 0, + "nullable": true + }, + "statusCode": { + "type": "integer", + "minimum": 100, + "maximum": 599, + "nullable": true + }, + "errorCode": { + "type": "string", + "nullable": true + }, + "metadataExpiresAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "deliveryId", + "number", + "status", + "startedAt", + "completedAt", + "nextRetryAt", + "durationMs", + "statusCode", + "errorCode", + "metadataExpiresAt" + ] + }, + "JsonValue": { + "nullable": true, + "oneOf": [ + { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/JsonValue" + } + }, + { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/JsonValue" + } + } + ] + }, + "OperationCapabilities": { + "type": "object", + "additionalProperties": false, + "properties": { + "cancellable": { + "type": "boolean" + }, + "watchable": { + "type": "boolean" + } + }, + "required": [ + "cancellable", + "watchable" + ] + }, + "OperationProgress": { + "type": "object", + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "current": { + "type": "integer", + "nullable": true + }, + "total": { + "type": "integer", + "nullable": true + } + }, + "required": [ + "code", + "current", + "total" + ] + }, + "OperationError": { + "type": "object", + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "details": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/JsonValue" + } + } + }, + "required": [ + "code", + "retryable", + "details" + ] + }, + "OperationActionRequired": { + "type": "object", + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "details": { + "type": "object", + "nullable": true, + "additionalProperties": { + "$ref": "#/components/schemas/JsonValue" + } + } + }, + "required": [ + "code", + "details" + ] + }, + "OrganizationOperation": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "nullable": true, + "enum": [ + null + ] + }, + "kind": { + "type": "string", + "enum": [ + "auth_projection_repair", + "session_lifecycle", + "auth_session_purge", + "label_projection_purge", + "billing_reconciliation", + "auto_top_up", + "campaign", + "production_enrollment", + "retention_sweep", + "webhook_redrive" + ] + }, + "resource": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "type", + "id" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "action_required", + "cancelling", + "succeeded", + "failed", + "cancelled" + ] + }, + "sequence": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "capabilities": { + "$ref": "#/components/schemas/OperationCapabilities" + }, + "progress": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationProgress" + } + ] + }, + "result": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/JsonValue" + } + ] + }, + "error": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationError" + } + ] + }, + "actionRequired": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationActionRequired" + } + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "kind", + "resource", + "status", + "sequence", + "capabilities", + "progress", + "result", + "error", + "actionRequired", + "createdAt", + "updatedAt", + "completedAt" + ] + }, + "ProjectOperation": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "organizationId": { + "type": "string", + "format": "uuid" + }, + "projectId": { + "type": "string", + "format": "uuid" + }, + "kind": { + "type": "string", + "enum": [ + "auth_projection_repair", + "session_lifecycle", + "auth_session_purge", + "label_projection_purge", + "billing_reconciliation", + "auto_top_up", + "campaign", + "production_enrollment", + "retention_sweep", + "webhook_redrive" + ] + }, + "resource": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "type", + "id" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "action_required", + "cancelling", + "succeeded", + "failed", + "cancelled" + ] + }, + "sequence": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "capabilities": { + "$ref": "#/components/schemas/OperationCapabilities" + }, + "progress": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationProgress" + } + ] + }, + "result": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/JsonValue" + } + ] + }, + "error": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationError" + } + ] + }, + "actionRequired": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationActionRequired" + } + ] + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "completedAt": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "required": [ + "id", + "organizationId", + "projectId", + "kind", + "resource", + "status", + "sequence", + "capabilities", + "progress", + "result", + "error", + "actionRequired", + "createdAt", + "updatedAt", + "completedAt" + ] + }, + "OperationTransition": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "sequence": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "fromStatus": { + "type": "string", + "enum": [ + "pending", + "running", + "action_required", + "cancelling", + "succeeded", + "failed", + "cancelled", + null + ], + "nullable": true + }, + "toStatus": { + "type": "string", + "enum": [ + "pending", + "running", + "action_required", + "cancelling", + "succeeded", + "failed", + "cancelled" + ] + }, + "reasonCode": { + "type": "string", + "nullable": true + }, + "occurredAt": { + "type": "string", + "format": "date-time" + }, + "snapshot": { + "type": "object", + "additionalProperties": false, + "properties": { + "progress": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationProgress" + } + ] + }, + "error": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationError" + } + ] + }, + "actionRequired": { + "nullable": true, + "allOf": [ + { + "$ref": "#/components/schemas/OperationActionRequired" + } + ] + } + }, + "required": [ + "progress", + "error", + "actionRequired" + ] + } + }, + "required": [ + "operationId", + "sequence", + "fromStatus", + "toStatus", + "reasonCode", + "occurredAt", + "snapshot" + ] + }, + "IdempotencyReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "key": { + "type": "string", + "minLength": 1, + "maxLength": 255 + }, + "replayed": { + "type": "boolean" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "key", + "replayed", + "createdAt", + "expiresAt" + ] + }, + "ReplayEventInput": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhookId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "webhookId" + ] + }, + "RetryWebhookDeliveryInput": { + "type": "object", + "additionalProperties": false, + "maxProperties": 0 + }, + "TestWebhookInput": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "eventType": { + "type": "string", + "default": "polymorfa.test", + "pattern": "^[a-z0-9][a-z0-9_.-]{0,127}$" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "eventType": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9_.-]{0,127}$" + }, + "body": { + "$ref": "#/components/schemas/EncodedEventPayload" + }, + "sessionId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "body", + "sessionId" + ] + } + ] + }, + "OrganizationEventReplayReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "eventId": { + "type": "string", + "format": "uuid" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "deliveryId", + "operationId", + "idempotency" + ] + }, + "ProjectEventReplayReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "eventId": { + "type": "string", + "format": "uuid" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "deliveryId", + "operationId", + "idempotency" + ] + }, + "OrganizationWebhookDeliveryRetryReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + }, + "attemptId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "deliveryId", + "attemptId", + "operationId", + "idempotency" + ] + }, + "ProjectWebhookDeliveryRetryReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + }, + "attemptId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "deliveryId", + "attemptId", + "operationId", + "idempotency" + ] + }, + "OrganizationWebhookTestReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "eventId": { + "type": "string", + "format": "uuid" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "deliveryId", + "operationId", + "idempotency" + ] + }, + "ProjectWebhookTestReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + }, + "eventId": { + "type": "string", + "format": "uuid" + }, + "deliveryId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "eventId", + "deliveryId", + "operationId", + "idempotency" + ] + }, + "OrganizationOperationCancellationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operation": { + "$ref": "#/components/schemas/OrganizationOperation" + }, + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "operation", + "operationId", + "idempotency" + ] + }, + "ProjectOperationCancellationReceipt": { + "type": "object", + "additionalProperties": false, + "properties": { + "operation": { + "$ref": "#/components/schemas/ProjectOperation" + }, + "operationId": { + "type": "string", + "format": "uuid" + }, + "idempotency": { + "$ref": "#/components/schemas/IdempotencyReceipt" + } + }, + "required": [ + "operation", + "operationId", + "idempotency" + ] + }, + "OperationConflictEnvelope": { + "type": "object", + "additionalProperties": false, + "properties": { + "error": { + "type": "string", + "enum": [ + "operation_conflict" + ] + }, + "code": { + "type": "string", + "enum": [ + "operation_conflict" + ] + }, + "operation": { + "oneOf": [ + { + "$ref": "#/components/schemas/OrganizationOperation" + }, + { + "$ref": "#/components/schemas/ProjectOperation" + } + ] + } + }, + "required": [ + "error", + "code", + "operation" + ] + }, + "IdempotencyConflictEnvelope": { + "type": "object", + "additionalProperties": false, + "properties": { + "error": { + "type": "string", + "enum": [ + "idempotency_conflict" + ] + }, + "code": { + "type": "string", + "enum": [ + "idempotency_conflict" + ] + } + }, + "required": [ + "error", + "code" + ] + }, + "OperationCancellationConflictEnvelope": { + "oneOf": [ + { + "$ref": "#/components/schemas/OperationConflictEnvelope" + }, + { + "$ref": "#/components/schemas/IdempotencyConflictEnvelope" + } + ] + } + }, + "responses": { + "Unauthorized": { + "description": "Missing/invalid credential for this audience.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "Forbidden": { + "description": "Authenticated but lacks the required scope/role/audience.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "Gone": { + "description": "The requested retained payload is no longer available.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "BadRequest": { + "description": "A path, query, or request-body value did not pass validation.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "PaymentRequired": { + "description": "The number's plan does not include this capability.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "PropagationPending": { + "description": "The change was stored, but a connected number has not confirmed it. Retry the request; the stored setting is already correct and is retried automatically.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "NotFound": { + "description": "The requested resource was not found inside the authenticated organization or project scope.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "Conflict": { + "description": "The request conflicts with the resource's current state.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "Unprocessable": { + "description": "The retained payload is unavailable or no longer replayable.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "OperationCancellationConflict": { + "description": "The operation cannot accept cancellation, or the idempotency key was reused for a different request.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OperationCancellationConflictEnvelope" + } + } + } + }, + "InternalError": { + "description": "The session-control publisher or testing-number persistence path is temporarily unavailable.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + }, + "NotImplemented": { + "description": "Endpoint registered; handler not yet wired to a repository.", + "headers": { + "X-Request-Id": { + "schema": { + "type": "string" + }, + "description": "Stable request correlation identifier." + }, + "Polymorfa-Version": { + "schema": { + "type": "string" + }, + "description": "API version applied to this response." + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorEnvelope" + } + } + } + } + } + } +} diff --git a/contracts/drafts/bansafe/source.json b/contracts/drafts/bansafe/source.json new file mode 100644 index 0000000..dce5b44 --- /dev/null +++ b/contracts/drafts/bansafe/source.json @@ -0,0 +1,17 @@ +{ + "repository": "polymorfa/polymorfa", + "sourceCommit": "579a53488d6af339ef358857ad0de2a45e8a5d30", + "sourceState": "pull-request-head", + "contracts": { + "messaging": { + "sourcePath": "apps/api/docs/openapi.json", + "snapshotPath": "contracts/drafts/bansafe/openapi.messaging.json", + "sha256": "6220a15d9f14ce177c526047612dd46bd1c8c69e1aaf3b56733b0490e3c3e0c8" + }, + "platform": { + "sourcePath": "apps/api/docs/openapi.management.json", + "snapshotPath": "contracts/drafts/bansafe/openapi.platform.json", + "sha256": "a7f9d3b449aa93ebdf1e52c5c04519dd405d963a2da59db85d43748f671c95bf" + } + } +} diff --git a/packages/typescript/README.md b/packages/typescript/README.md index 183e0af..1a8eed1 100644 --- a/packages/typescript/README.md +++ b/packages/typescript/README.md @@ -150,6 +150,48 @@ The pairing URL is returned once. An idempotent replay returns the same link record with `url: null`. `customers.list()` preserves both the Customer array and the cursor metadata from the API response. +## BanSafe Health and telemetry + +`Client.banSafe` reads Health, telemetry collection status, the fixed +signal catalogue, findings, restrictions, incidents, claims, and Health action +history. Paged methods preserve the API's `data` array and `page` metadata. + +```ts +const health = await platform.banSafe.getHealth("support"); +const telemetry = await platform.banSafe.getTelemetry("support"); +const actions = await platform.banSafe.listHealthActions({ + projectId: "project_123", + session: "support", + status: "succeeded", +}); + +console.log( + health.data.data.health, + telemetry.data.data.collection.state, + actions.data.page.hasMore, +); +``` + +Use `platform.projects` for project Safe Mode, warm-up, Ban Insurance evidence, +and Health policy settings. Use `platform.sessions` for one number's Safe Mode +override. + +```ts +const policy = await platform.projects.getHealthPolicy("project_123"); +await platform.projects.updateHealthPolicy("project_123", { + version: policy.data.data.version, + enabled: true, + threshold: 50, + sessionAction: "slow_down", + slowDownMps: 0.5, + emailNotification: true, + webhookNotification: true, +}); +``` + +Finding acknowledgement and restriction appeals require a signed-in dashboard +user. The organization-key SDK does not expose those two mutations. + ## Browser client tokens `MessagingClient.clientTokens` mints short-lived tokens and manages the live @@ -1213,7 +1255,7 @@ pending session. Connected links cannot be cancelled. The source exposes no list, recover, or history operation. `Client.quickLinkSettings.retrieve` and `update` map the management -`GET /v1/quicklink` and `PUT /v1/quicklink` operations. Use them on the root +`GET /platform/quicklink` and `PUT /platform/quicklink` operations. Use them on the root organization client or an immutable project view: ```ts @@ -1228,7 +1270,7 @@ const projectSettings = await platform These methods manage saved settings only. Hosted lifecycle methods stay on `MessagingClient.quickLinks`, not `Client` or `client.project(...)`, because -the `/api/quicklinks/{id}` routes do not carry an immutable project path for an +the `/messaging/quicklinks/{id}` routes do not carry an immutable project path for an organization-key project view. Console-only logo routes are outside the SDK. ## Management session lifecycle diff --git a/packages/typescript/src/client.ts b/packages/typescript/src/client.ts index f06667b..8c8c41a 100644 --- a/packages/typescript/src/client.ts +++ b/packages/typescript/src/client.ts @@ -16,6 +16,7 @@ import { ApiKeysResource } from "./platform/api-keys.js"; import { AudiencesResource } from "./platform/audiences.js"; import { AuditLogsResource } from "./platform/audit-logs.js"; import { BillingResource } from "./platform/billing.js"; +import { BanSafeResource } from "./platform/bansafe.js"; import { CampaignsResource } from "./platform/campaigns.js"; import { CustomersResource } from "./platform/customers.js"; import { @@ -63,6 +64,7 @@ export interface OrganizationControlPlaneResources { readonly audiences: AudiencesResource; readonly auditLogs: AuditLogsResource; readonly billing: BillingResource; + readonly banSafe: BanSafeResource; readonly campaigns: CampaignsResource; readonly customers: CustomersResource; readonly members: MembersResource; @@ -150,6 +152,7 @@ class ClientImplementation implements ClientBase { audiences: new AudiencesResource(this.#transport), auditLogs: new AuditLogsResource(this.#transport), billing: new BillingResource(this.#transport), + banSafe: new BanSafeResource(this.#transport), campaigns: new CampaignsResource(this.#transport), customers: new CustomersResource(this.#transport), members: new MembersResource(this.#transport), diff --git a/packages/typescript/src/index.ts b/packages/typescript/src/index.ts index a7ff083..fe0389d 100644 --- a/packages/typescript/src/index.ts +++ b/packages/typescript/src/index.ts @@ -455,6 +455,7 @@ export { AudiencesResource } from "./platform/audiences.js"; export { ApiKeysResource } from "./platform/api-keys.js"; export { AuditLogsResource } from "./platform/audit-logs.js"; export { BillingResource } from "./platform/billing.js"; +export { BanSafeResource } from "./platform/bansafe.js"; export { CampaignsResource } from "./platform/campaigns.js"; export { CustomersResource } from "./platform/customers.js"; export { MediaResource } from "./platform/media.js"; @@ -546,6 +547,93 @@ export type { UpdateBillingReminderSettingsRequest, UpdateCustomerRequest, } from "./platform/types.js"; +export type { + BanSafeAppealState, + BanSafeClaim, + BanSafeClaimEvidence, + BanSafeClaimsEnvelope, + BanSafeClaimStatus, + BanSafeClaimVerdict, + BanSafeCollectionEnvelope, + BanSafeCollectionSession, + BanSafeCollectionState, + BanSafeCollectionStatus, + BanSafeEnforcementEnvelope, + BanSafeEnforcementRung, + BanSafeEnforcementSummary, + BanSafeFinding, + BanSafeFindingsEnvelope, + BanSafeFindingSeverity, + BanSafeFindingStatus, + BanSafeHealthAction, + BanSafeHealthActionKind, + BanSafeHealthActionMode, + BanSafeHealthActionOutcome, + BanSafeHealthActionsEnvelope, + BanSafeHealthActionStatus, + BanSafeHealthBand, + BanSafeHealthEnvelope, + BanSafeHealthExplanation, + BanSafeHealthExplanationFactor, + BanSafeHealthExplanationGroup, + BanSafeHealthHistory, + BanSafeHealthPoint, + BanSafeHealthProbabilities, + BanSafeHealthProjection, + BanSafeHealthReliability, + BanSafeHealthSource, + BanSafeHealthState, + BanSafeHealthUnavailableReason, + BanSafeIncident, + BanSafeIncidentKind, + BanSafeIncidentReceipt, + BanSafeIncidentsEnvelope, + BanSafeNumber, + BanSafeNumberDetail, + BanSafeNumberEnforcement, + BanSafeNumberWarmup, + BanSafeObservedAccountState, + BanSafeSignal, + BanSafeSignalDefinition, + BanSafeSignalKind, + BanSafeSignalUnit, + BanSafeTelemetryDetail, + BanSafeTelemetryHistoryEnvelope, + BanSafeTelemetrySnapshot, + CursorEnvelope, + CursorPageMetadata, + ListBanSafeClaimsParams, + ListBanSafeCollectionParams, + ListBanSafeEnforcementParams, + ListBanSafeFindingsParams, + ListBanSafeHealthActionsParams, + ListBanSafeHealthHistoryParams, + ListBanSafeHealthParams, + ListBanSafeIncidentsParams, + ListBanSafeTelemetryHistoryParams, + ProjectHealthPolicy, + ProjectHealthPolicyIntegrations, + ProjectHealthSessionAction, + ProjectInsuranceEvidence, + ProjectSafeMode, + ProjectWarmupPlan, + ReportBanSafeIncidentRequest, + SafeModeApplied, + SafeModeOverride, + SafeModePacing, + SafeModePresence, + SafeModeReads, + SafeModeSettings, + SafeModeTyping, + SessionSafeMode, + UpdateProjectHealthPolicyRequest, + UpdateProjectInsuranceEvidenceRequest, + UpdateProjectSafeModeRequest, + UpdateProjectWarmupPlanRequest, + UpdateSessionSafeModeRequest, + WarmupCurvePoint, + WarmupPlanSettings, +} from "./platform/types.js"; export { RawClient, type ProjectScopedRawClient } from "./raw.js"; export type { ApiResponse, diff --git a/packages/typescript/src/platform/bansafe.ts b/packages/typescript/src/platform/bansafe.ts new file mode 100644 index 0000000..1adf608 --- /dev/null +++ b/packages/typescript/src/platform/bansafe.ts @@ -0,0 +1,186 @@ +import { HttpTransport } from "../transport/http.js"; +import type { + ApiResponse, + QueryValue, + RequestOptions, +} from "../transport/types.js"; +import type { + BanSafeClaim, + BanSafeClaimsEnvelope, + BanSafeCollectionEnvelope, + BanSafeEnforcementEnvelope, + BanSafeFindingsEnvelope, + BanSafeHealthActionsEnvelope, + BanSafeHealthEnvelope, + BanSafeHealthHistory, + BanSafeIncident, + BanSafeIncidentReceipt, + BanSafeIncidentsEnvelope, + BanSafeSignalDefinition, + BanSafeNumberDetail, + BanSafeTelemetryDetail, + BanSafeTelemetryHistoryEnvelope, + DataEnvelope, + ListBanSafeClaimsParams, + ListBanSafeCollectionParams, + ListBanSafeEnforcementParams, + ListBanSafeFindingsParams, + ListBanSafeHealthActionsParams, + ListBanSafeHealthHistoryParams, + ListBanSafeHealthParams, + ListBanSafeIncidentsParams, + ListBanSafeTelemetryHistoryParams, + ReportBanSafeIncidentRequest, +} from "./types.js"; + +export class BanSafeResource { + constructor(private readonly transport: HttpTransport) {} + + listHealth( + params: ListBanSafeHealthParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/health", params, options); + } + + getHealth( + session: string, + options: RequestOptions = {}, + ): Promise>> { + return this.get( + `/platform/bansafe/health/${encodeURIComponent(session)}`, + {}, + options, + ); + } + + listHealthHistory( + session: string, + params: ListBanSafeHealthHistoryParams = {}, + options: RequestOptions = {}, + ): Promise>> { + return this.get( + `/platform/bansafe/health/${encodeURIComponent(session)}/history`, + params, + options, + ); + } + + listSignals( + options: RequestOptions = {}, + ): Promise>> { + return this.get("/platform/bansafe/signals", {}, options); + } + + getTelemetry( + session: string, + options: RequestOptions = {}, + ): Promise>> { + return this.get( + `/platform/bansafe/telemetry/${encodeURIComponent(session)}`, + {}, + options, + ); + } + + listTelemetryHistory( + session: string, + params: ListBanSafeTelemetryHistoryParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get( + `/platform/bansafe/telemetry/${encodeURIComponent(session)}/history`, + params, + options, + ); + } + + listCollection( + params: ListBanSafeCollectionParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/collection", params, options); + } + + listHealthActions( + params: ListBanSafeHealthActionsParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/health-actions", params, options); + } + + listFindings( + params: ListBanSafeFindingsParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/findings", params, options); + } + + listEnforcement( + params: ListBanSafeEnforcementParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/enforcement", params, options); + } + + listIncidents( + params: ListBanSafeIncidentsParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/incidents", params, options); + } + + createIncident( + body: ReportBanSafeIncidentRequest, + options: RequestOptions, + ): Promise>> { + return this.transport.request({ + method: "POST", + path: "/platform/bansafe/incidents", + body, + ...options, + }); + } + + retractIncident( + incidentId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.transport.request({ + method: "POST", + path: `/platform/bansafe/incidents/${encodeURIComponent(incidentId)}/retract`, + ...options, + }); + } + + listClaims( + params: ListBanSafeClaimsParams = {}, + options: RequestOptions = {}, + ): Promise> { + return this.get("/platform/bansafe/claims", params, options); + } + + getClaim( + claimId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.get( + `/platform/bansafe/claims/${encodeURIComponent(claimId)}`, + {}, + options, + ); + } + + private get( + path: string, + params: object, + options: RequestOptions, + ): Promise> { + return this.transport.request({ + method: "GET", + path, + query: params as Readonly>, + ...options, + }); + } +} diff --git a/packages/typescript/src/platform/projects.ts b/packages/typescript/src/platform/projects.ts index de335d2..b4635f2 100644 --- a/packages/typescript/src/platform/projects.ts +++ b/packages/typescript/src/platform/projects.ts @@ -8,6 +8,14 @@ import type { ProductionEnrollmentResult, Project, ProjectWithStats, + ProjectHealthPolicy, + ProjectInsuranceEvidence, + ProjectSafeMode, + ProjectWarmupPlan, + UpdateProjectHealthPolicyRequest, + UpdateProjectInsuranceEvidenceRequest, + UpdateProjectSafeModeRequest, + UpdateProjectWarmupPlanRequest, } from "./types.js"; export class ProjectsResource { @@ -35,6 +43,98 @@ export class ProjectsResource { }); } + getSafeMode( + projectId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.getSetting(projectId, "safe-mode", options); + } + + updateSafeMode( + projectId: string, + body: UpdateProjectSafeModeRequest, + options: RequestOptions = {}, + ): Promise>> { + return this.updateSetting( + projectId, + "safe-mode", + body, + options, + ); + } + + getWarmupPlan( + projectId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.getSetting( + projectId, + "warmup-plan", + options, + ); + } + + updateWarmupPlan( + projectId: string, + body: UpdateProjectWarmupPlanRequest, + options: RequestOptions = {}, + ): Promise>> { + return this.updateSetting( + projectId, + "warmup-plan", + body, + options, + ); + } + + getInsuranceEvidence( + projectId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.getSetting( + projectId, + "insurance-evidence", + options, + ); + } + + updateInsuranceEvidence( + projectId: string, + body: UpdateProjectInsuranceEvidenceRequest, + options: RequestOptions = {}, + ): Promise>> { + return this.updateSetting( + projectId, + "insurance-evidence", + body, + options, + ); + } + + getHealthPolicy( + projectId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.getSetting( + projectId, + "health-policy", + options, + ); + } + + updateHealthPolicy( + projectId: string, + body: UpdateProjectHealthPolicyRequest, + options: RequestOptions = {}, + ): Promise>> { + return this.updateSetting( + projectId, + "health-policy", + body, + options, + ); + } + requestProductionEnrollment( projectId: string, body: ProductionEnrollmentRequest, @@ -76,4 +176,32 @@ export class ProjectsResource { ...options, }); } + + private getSetting( + projectId: string, + setting: + "safe-mode" | "warmup-plan" | "insurance-evidence" | "health-policy", + options: RequestOptions, + ): Promise>> { + return this.transport.request({ + method: "GET", + path: `/platform/projects/${encodeURIComponent(projectId)}/${setting}`, + ...options, + }); + } + + private updateSetting( + projectId: string, + setting: + "safe-mode" | "warmup-plan" | "insurance-evidence" | "health-policy", + body: unknown, + options: RequestOptions, + ): Promise>> { + return this.transport.request({ + method: "PUT", + path: `/platform/projects/${encodeURIComponent(projectId)}/${setting}`, + body, + ...options, + }); + } } diff --git a/packages/typescript/src/platform/sessions.ts b/packages/typescript/src/platform/sessions.ts index 91d15e1..801435d 100644 --- a/packages/typescript/src/platform/sessions.ts +++ b/packages/typescript/src/platform/sessions.ts @@ -14,6 +14,8 @@ import type { SessionStartResult, SessionStopResult, SessionTierOverrideRequest, + SessionSafeMode, + UpdateSessionSafeModeRequest, } from "./types.js"; export class PlatformSessionsResource { @@ -120,6 +122,30 @@ export class PlatformSessionsResource { ...options, }); } + + getSafeMode( + sessionId: string, + options: RequestOptions = {}, + ): Promise>> { + return this.transport.request({ + method: "GET", + path: `${sessionPath(sessionId)}/safe-mode`, + ...options, + }); + } + + updateSafeMode( + sessionId: string, + body: UpdateSessionSafeModeRequest, + options: RequestOptions = {}, + ): Promise>> { + return this.transport.request({ + method: "PUT", + path: `${sessionPath(sessionId)}/safe-mode`, + body, + ...options, + }); + } } function sessionPath(sessionId: string): string { diff --git a/packages/typescript/src/platform/types.ts b/packages/typescript/src/platform/types.ts index 65a06f4..ce63bc3 100644 --- a/packages/typescript/src/platform/types.ts +++ b/packages/typescript/src/platform/types.ts @@ -489,3 +489,548 @@ export interface CreateTestingSessionRequest { readonly name?: string; readonly country?: "US" | "GB" | "BR" | "IN"; } + +export interface CursorPageMetadata { + readonly nextCursor: string | null; + readonly hasMore: boolean; +} + +export interface CursorEnvelope { + readonly data: readonly T[]; + readonly page: CursorPageMetadata; +} + +export type BanSafeHealthBand = + "good" | "fair" | "poor" | "failing" | "unknown"; +export type BanSafeHealthState = + "healthy" | "limited" | "restricted" | "banned"; +export type BanSafeHealthSource = "rules_v1" | "ml_model" | "unavailable"; +export type BanSafeHealthReliability = + "rules_based" | "validated" | "unavailable"; +export type BanSafeHealthUnavailableReason = + "no_active_model" | "invalid_active_model" | "insufficient_fresh_features"; +export type BanSafeEnforcementRung = + "none" | "notify" | "throttle" | "block_cold" | "suspend"; +export type BanSafeAppealState = "none" | "requested" | "granted" | "denied"; + +export interface BanSafeHealthProbabilities { + readonly healthy: number; + readonly limited: number; + readonly restricted: number; + readonly banned: number; +} + +export type BanSafeHealthExplanationGroup = + "direct_condition" | "delivery" | "connection" | "conduct" | "cadence"; + +export interface BanSafeHealthExplanationFactor { + readonly group: BanSafeHealthExplanationGroup; + readonly key: string; + readonly penalty: number; + readonly observedValue: number; + readonly sampleSize: number; +} + +export interface BanSafeHealthExplanation { + readonly penalties: { + readonly conduct: number; + readonly delivery: number; + readonly connection: number; + readonly restriction: number; + readonly total: number; + }; + readonly factors: readonly BanSafeHealthExplanationFactor[]; + readonly measuredGroups: readonly BanSafeHealthExplanationGroup[]; + readonly missingGroups: readonly BanSafeHealthExplanationGroup[]; +} + +export interface BanSafeObservedAccountState { + readonly state: BanSafeHealthState; + readonly observedAt: string; + readonly source: "account_check" | "restriction_event"; +} + +export interface BanSafeHealthProjection { + readonly health: number | null; + readonly band: BanSafeHealthBand; + readonly healthSource: BanSafeHealthSource; + readonly healthEstimatorVersion: string | null; + readonly healthModelVersion: string | null; + readonly healthEvaluatedAt: string | null; + readonly healthFeatureCoverage: number | null; + readonly healthReliability: BanSafeHealthReliability; + readonly healthUnavailableReason: BanSafeHealthUnavailableReason | null; + readonly healthProbabilities: BanSafeHealthProbabilities | null; + readonly mostLikelyHealthState: BanSafeHealthState | null; + readonly healthExplanation: BanSafeHealthExplanation | null; + readonly observedAccountState: BanSafeObservedAccountState | null; +} + +export interface BanSafeNumberEnforcement { + readonly rung: BanSafeEnforcementRung; + readonly previousRung: BanSafeEnforcementRung; + readonly organizationFloor: BanSafeEnforcementRung; + readonly reason: string; + readonly source: "automatic" | "operator"; + readonly throughputPerMinute: number | null; + readonly blocksUnsolicited: boolean; + readonly suspended: boolean; + readonly startedAt: string; + readonly eligibleLiftAt: string | null; + readonly exitProgress: number; + readonly blockingFindings: readonly string[]; + readonly operatorHold: boolean; + readonly appealState: BanSafeAppealState; + readonly state: "applied" | "applying"; +} + +export interface BanSafeNumber extends BanSafeHealthProjection { + readonly sessionId: string; + readonly session: string; + readonly phoneNumber: string; + readonly projectId: string; + readonly enforcement: BanSafeNumberEnforcement | null; +} + +export interface WarmupCurvePoint { + readonly day: number; + readonly allowance: number; +} + +export interface BanSafeNumberWarmup { + readonly enabled: boolean; + readonly tenureSource: "history" | "link" | "plan" | null; + readonly tenureDay: number; + readonly allowance: number | null; + readonly sentToday: number | null; + readonly resetsAt: string | null; + readonly curve: readonly WarmupCurvePoint[]; +} + +export interface BanSafeNumberDetail extends BanSafeNumber { + readonly warmup: BanSafeNumberWarmup; + readonly findings: readonly BanSafeFinding[]; + readonly liftRequires: string | null; + readonly appealState: BanSafeAppealState; +} + +export interface BanSafeHealthPoint extends Omit< + BanSafeHealthProjection, + "band" | "healthEvaluatedAt" +> { + readonly band: BanSafeHealthBand | null; + readonly healthEvaluatedAt: string; +} + +export interface BanSafeHealthHistory { + readonly sessionId: string; + readonly session: string; + readonly points: readonly BanSafeHealthPoint[]; +} + +export type BanSafeFindingStatus = + "open" | "acknowledged" | "resolved" | "not_measured"; +export type BanSafeFindingSeverity = "info" | "warning" | "critical"; + +export interface BanSafeFinding { + readonly id: string | null; + readonly key: string; + readonly title: string; + readonly summary: string; + readonly fix: string; + readonly status: BanSafeFindingStatus; + readonly severity: BanSafeFindingSeverity | null; + readonly occurrences: number; + readonly reopenedCount: number; + readonly evidence: Readonly>; + readonly sessionId: string; + readonly session: string; + readonly phoneNumber: string; + readonly firstSeenAt: string | null; + readonly lastSeenAt: string | null; + readonly acknowledgedAt: string | null; + readonly acknowledgedBy: string | null; + readonly acknowledgementNote: string | null; + readonly snoozedUntil: string | null; + readonly resolvedAt: string | null; + readonly resolveReason: + "clean" | "key_retired" | "number_removed" | "stale" | null; +} + +export interface BanSafeEnforcementSummary extends BanSafeHealthProjection { + readonly sessionId: string; + readonly session: string; + readonly phoneNumber: string; + readonly projectId: string; + readonly rung: BanSafeEnforcementRung; + readonly previousRung: BanSafeEnforcementRung; + readonly organizationFloor: BanSafeEnforcementRung; + readonly reason: string; + readonly source: "automatic" | "operator"; + readonly throughputPerMinute: number | null; + readonly blocksUnsolicited: boolean; + readonly suspended: boolean; + readonly blockingFindings: readonly string[]; + readonly startedAt: string; + readonly eligibleLiftAt: string | null; + readonly liftRequires: string; + readonly operatorHold: boolean; + readonly appealState: BanSafeAppealState; + readonly state: "applied" | "applying"; +} + +export type BanSafeIncidentKind = + | "cap_warning" + | "cap_reached" + | "timelock" + | "temporary_ban" + | "permanent_ban" + | "connect_blocked" + | "customer_report"; + +export interface BanSafeIncident { + readonly id: string; + readonly sessionId: string; + readonly session: string; + readonly phoneNumber: string; + readonly projectId: string; + readonly kind: BanSafeIncidentKind; + readonly source: "runtime" | "customer"; + readonly resolution: string; + readonly ambiguous: boolean; + readonly startedAt: string; + readonly endsAt: string | null; + readonly closedAt: string | null; + readonly closedBy: string | null; + readonly claimId: string | null; + readonly note: string | null; + readonly reportedBy: string | null; + readonly createdAt: string; +} + +export interface ReportBanSafeIncidentRequest { + readonly session: string; + readonly occurredAt?: string; + readonly note?: string; +} + +export interface BanSafeIncidentReceipt { + readonly incidentId: string; + readonly created: boolean; + readonly sessionId: string; + readonly session: string; + readonly occurredAt: string; +} + +export type BanSafeClaimStatus = + "filed" | "under_review" | "approved" | "denied" | "paid" | "reversed"; +export type BanSafeClaimVerdict = + | "other_device" + | "customer_conduct" + | "shared_network" + | "ours" + | "inconclusive"; + +export interface BanSafeClaimEvidence { + readonly attributionRuleVersion: number | null; + readonly windowDays: number; + readonly deviceEvidence: boolean; + readonly otherDevices: number; + readonly restrictedInWindow: boolean; + readonly criticalFindingDays: number; + readonly sharedConnection: boolean; + readonly measuredHours: number; +} + +export interface BanSafeClaim { + readonly id: string; + readonly incidentId: string; + readonly sessionId: string; + readonly session: string; + readonly phoneNumber: string; + readonly projectId: string; + readonly status: BanSafeClaimStatus; + readonly verdict: BanSafeClaimVerdict; + readonly windowStart: string; + readonly windowEnd: string; + readonly measuredCents: number; + readonly capCents: number; + readonly amountCents: number; + readonly evidence: BanSafeClaimEvidence; + readonly summary: string; + readonly reason: string; + readonly decidedAt: string | null; + readonly paidAt: string | null; + readonly createdAt: string; +} + +export interface ListBanSafeHealthParams { + readonly projectId?: string; + readonly cursor?: string; + readonly limit?: number; +} + +export interface ListBanSafeHealthHistoryParams { + readonly since?: string; + readonly limit?: number; +} + +export interface ListBanSafeFindingsParams extends ListBanSafeHealthParams { + readonly session?: string; + readonly status?: Exclude; + readonly severity?: BanSafeFindingSeverity; +} + +export interface ListBanSafeEnforcementParams extends ListBanSafeHealthParams { + readonly rung?: BanSafeEnforcementRung; +} + +export interface ListBanSafeIncidentsParams extends ListBanSafeHealthParams { + readonly session?: string; +} + +export interface ListBanSafeClaimsParams extends ListBanSafeHealthParams { + readonly session?: string; + readonly status?: BanSafeClaimStatus; +} + +export type BanSafeSignalKind = + "number" | "boolean" | "enum" | "histogram" | "code_counts"; +export type BanSafeSignalUnit = + "count" | "milliseconds" | "unix_milliseconds" | "ratio" | "none"; + +export interface BanSafeSignalDefinition { + readonly key: string; + readonly label: string; + readonly group: string; + readonly kind: BanSafeSignalKind; + readonly unit: BanSafeSignalUnit; + readonly description: string; +} + +export interface BanSafeSignal extends BanSafeSignalDefinition { + readonly measured: boolean; + readonly value: number | boolean | string | readonly number[] | null; + readonly sampleSize: number | null; + readonly codes: + readonly { readonly code: number; readonly count: number }[] | null; +} + +export type BanSafeCollectionState = + "fresh" | "stale" | "not_collected" | "unsupported"; + +export interface BanSafeCollectionStatus { + readonly state: BanSafeCollectionState; + readonly latestFlushedAt: string | null; + readonly latestReceivedAt: string | null; + readonly freshUntil: string | null; + readonly recordVersion: number | null; + readonly collectorVersion: number | null; + readonly partial: boolean | null; + readonly droppedRecords: number | null; +} + +export interface BanSafeTelemetrySnapshot { + readonly bucketStart: string; + readonly flushedAt: string; + readonly receivedAt: string; + readonly partial: boolean; + readonly recordVersion: number | null; + readonly signals: readonly BanSafeSignal[]; +} + +export interface BanSafeCollectionSession { + readonly sessionId: string; + readonly session: string; + readonly projectId: string; + readonly collection: BanSafeCollectionStatus; +} + +export interface BanSafeTelemetryDetail extends BanSafeCollectionSession { + readonly snapshot: BanSafeTelemetrySnapshot | null; +} + +export interface ListBanSafeTelemetryHistoryParams { + readonly since?: string; + readonly until?: string; + readonly cursor?: string; + readonly limit?: number; +} + +export type ListBanSafeCollectionParams = ListBanSafeHealthParams; + +export type BanSafeHealthActionMode = "apply" | "clear"; +export type BanSafeHealthActionKind = + "stop" | "slow_down" | "log_out" | "email" | "webhook"; +export type BanSafeHealthActionStatus = + "pending" | "running" | "succeeded" | "failed" | "cancelled"; +export type BanSafeHealthActionOutcome = + | "applied" + | "cleared" + | "notification_queued" + | "superseded" + | "expired" + | "not_applied" + | "delivery_failed"; + +export interface BanSafeHealthAction { + readonly id: string; + readonly sessionId: string; + readonly session: string; + readonly projectId: string; + readonly mode: BanSafeHealthActionMode; + readonly action: BanSafeHealthActionKind; + readonly status: BanSafeHealthActionStatus; + readonly health: number; + readonly threshold: number; + readonly healthSource: Exclude; + readonly estimatorVersion: string; + readonly modelVersion: string | null; + readonly slowDownMps: number | null; + readonly evaluatedAt: string; + readonly createdAt: string; + readonly completedAt: string | null; + readonly outcome: BanSafeHealthActionOutcome | null; +} + +export interface ListBanSafeHealthActionsParams extends ListBanSafeHealthParams { + readonly session?: string; + readonly status?: BanSafeHealthActionStatus; +} + +export type BanSafeHealthEnvelope = CursorEnvelope; +export type BanSafeFindingsEnvelope = CursorEnvelope; +export type BanSafeEnforcementEnvelope = + CursorEnvelope; +export type BanSafeIncidentsEnvelope = CursorEnvelope; +export type BanSafeClaimsEnvelope = CursorEnvelope; +export type BanSafeTelemetryHistoryEnvelope = + CursorEnvelope; +export type BanSafeCollectionEnvelope = + CursorEnvelope; +export type BanSafeHealthActionsEnvelope = CursorEnvelope; + +export type SafeModePresence = "dark" | "online_while_sending" | "online_hours"; +export type SafeModeTyping = "off" | "before_text" | "before_all"; +export type SafeModeReads = "off" | "replied_chats" | "all_inbound"; +export type SafeModePacing = "off" | "jittered" | "conversation"; + +export interface SafeModeSettings { + readonly presence: SafeModePresence; + readonly typing: SafeModeTyping; + readonly reads: SafeModeReads; + readonly pacing: SafeModePacing; + readonly onlineStart: number; + readonly onlineEnd: number; +} + +export interface UpdateProjectSafeModeRequest { + readonly presence?: SafeModePresence; + readonly typing?: SafeModeTyping; + readonly reads?: SafeModeReads; + readonly pacing?: SafeModePacing; + readonly onlineStart?: number; + readonly onlineEnd?: number; +} + +export interface ProjectSafeMode { + readonly projectId: string; + readonly ceiling: SafeModeSettings; + readonly entitled: boolean; + readonly entitlementReason: string | null; +} + +export interface SafeModeOverride { + readonly presence: SafeModePresence | "inherit"; + readonly typing: SafeModeTyping | "inherit"; + readonly reads: SafeModeReads | "inherit"; + readonly pacing: SafeModePacing | "inherit"; +} + +export interface SafeModeApplied { + readonly observedAt: string; + readonly presence: string | null; + readonly typing: string | null; + readonly reads: string | null; + readonly pacing: string | null; +} + +export interface SessionSafeMode { + readonly session: string; + readonly projectId: string; + readonly project: SafeModeSettings; + readonly override: SafeModeOverride; + readonly effective: SafeModeSettings; + readonly applied: SafeModeApplied | null; + readonly mismatch: boolean; + readonly entitled: boolean; + readonly entitlementReason: string | null; +} + +export interface UpdateSessionSafeModeRequest { + readonly presence?: SafeModePresence | "inherit"; + readonly typing?: SafeModeTyping | "inherit"; + readonly reads?: SafeModeReads | "inherit"; + readonly pacing?: SafeModePacing | "inherit"; +} + +export interface WarmupPlanSettings { + readonly enabled: boolean; + readonly warmupDays: number; + readonly dailyStart: number; +} + +export interface ProjectWarmupPlan { + readonly projectId: string; + readonly plan: WarmupPlanSettings; + readonly ceiling: number; + readonly curve: readonly WarmupCurvePoint[]; + readonly entitled: boolean; + readonly entitlementReason: string | null; +} + +export interface UpdateProjectWarmupPlanRequest { + readonly enabled?: boolean; + readonly warmupDays?: number; + readonly dailyStart?: number; +} + +export interface ProjectInsuranceEvidence { + readonly projectId: string; + readonly enabled: boolean; + readonly banInsuranceIncluded: boolean; +} + +export interface UpdateProjectInsuranceEvidenceRequest { + readonly enabled: boolean; +} + +export type ProjectHealthSessionAction = + "none" | "stop" | "slow_down" | "log_out"; + +export interface ProjectHealthPolicyIntegrations { + readonly emailConfigured: boolean; + readonly webhookConfigured: boolean; +} + +export interface ProjectHealthPolicy { + readonly projectId: string; + readonly version: number; + readonly enabled: boolean; + readonly threshold: number; + readonly sessionAction: ProjectHealthSessionAction; + readonly slowDownMps: number | null; + readonly emailNotification: boolean; + readonly webhookNotification: boolean; + readonly integrations: ProjectHealthPolicyIntegrations; +} + +export interface UpdateProjectHealthPolicyRequest { + readonly version: number; + readonly enabled: boolean; + readonly threshold: number; + readonly sessionAction: ProjectHealthSessionAction; + readonly slowDownMps: number | null; + readonly emailNotification: boolean; + readonly webhookNotification: boolean; +} diff --git a/packages/typescript/src/transport/http.ts b/packages/typescript/src/transport/http.ts index 01192dc..f670727 100644 --- a/packages/typescript/src/transport/http.ts +++ b/packages/typescript/src/transport/http.ts @@ -370,6 +370,10 @@ function apiError( function errorMessage(body: unknown, status: number): string { if (typeof body === "object" && body !== null) { const record = body as Record; + if (typeof record.error === "object" && record.error !== null) { + const message = (record.error as Record).message; + if (typeof message === "string") return message; + } if (typeof record.error === "string") return record.error; if (typeof record.message === "string") return record.message; } @@ -379,7 +383,12 @@ function errorMessage(body: unknown, status: number): string { function errorCode(body: unknown): Pick { if (typeof body === "object" && body !== null) { - const code = (body as Record).code; + const record = body as Record; + if (typeof record.error === "object" && record.error !== null) { + const code = (record.error as Record).code; + if (typeof code === "string") return { code }; + } + const code = record.code; if (typeof code === "string") return { code }; } return {}; diff --git a/packages/typescript/test/bansafe-contract.test.ts b/packages/typescript/test/bansafe-contract.test.ts new file mode 100644 index 0000000..d10aa9c --- /dev/null +++ b/packages/typescript/test/bansafe-contract.test.ts @@ -0,0 +1,103 @@ +import { createHash } from "node:crypto"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { describe, expect, it } from "vitest"; + +import { Client } from "../src/index.js"; +import { ORGANIZATION_API_KEY } from "./support/credentials.js"; + +const root = resolve(import.meta.dirname, "../../.."); +const source = JSON.parse( + readFileSync(resolve(root, "contracts/drafts/bansafe/source.json"), "utf8"), +) as { + sourceState: string; + contracts: Record; +}; +const coverage = JSON.parse( + readFileSync(resolve(root, "contracts/drafts/bansafe/coverage.json"), "utf8"), +) as { + platformSha256: string; + covered: number; + excluded: number; + missing: number; + operations: Array<{ + operationId: string; + method: string; + path: string; + status: "covered" | "excluded"; + sdkPath?: string; + }>; +}; +const platform = JSON.parse( + readFileSync(resolve(root, source.contracts.platform!.snapshotPath), "utf8"), +) as { + paths: Record< + string, + Record< + string, + { operationId?: string; tags?: string[]; description?: string } + > + >; +}; + +describe("BanSafe draft contract coverage", () => { + it("pins the generated draft by content hash without claiming a merged source", () => { + expect(source.sourceState).toBe("pull-request-head"); + for (const contract of Object.values(source.contracts)) { + const hash = createHash("sha256") + .update(readFileSync(resolve(root, contract.snapshotPath))) + .digest("hex"); + expect(hash).toBe(contract.sha256); + } + expect(coverage.platformSha256).toBe(source.contracts.platform!.sha256); + }); + + it("accounts for every generated BanSafe operation", () => { + const generated = Object.entries(platform.paths).flatMap(([path, item]) => + Object.entries(item) + .filter( + ([method, operation]) => + ["get", "post", "put", "patch", "delete"].includes(method) && + operation.tags?.includes("bansafe"), + ) + .map(([method, operation]) => ({ + operationId: operation.operationId, + method: method.toUpperCase(), + path, + })), + ); + expect( + coverage.operations.map(({ operationId, method, path }) => ({ + operationId, + method, + path, + })), + ).toEqual(generated); + expect(coverage).toMatchObject({ covered: 25, excluded: 2, missing: 0 }); + }); + + it("maps covered operations to methods and excludes dashboard-only actions", () => { + const client = new Client({ + credential: { + type: "organizationApiKey", + value: ORGANIZATION_API_KEY, + }, + baseUrl: "https://example.invalid", + }); + for (const operation of coverage.operations) { + if (operation.status === "excluded") continue; + const path = operation.sdkPath!.replace(/^Client\./, "").split("."); + let value: unknown = client; + for (const part of path) value = (value as Record)[part]; + expect(typeof value, operation.sdkPath).toBe("function"); + } + + expect( + coverage.operations + .filter(({ status }) => status === "excluded") + .map(({ operationId }) => operationId), + ).toEqual(["acknowledgeBanSafeFinding", "appealBanSafeEnforcement"]); + expect(client.banSafe).not.toHaveProperty("acknowledgeFinding"); + expect(client.banSafe).not.toHaveProperty("appealEnforcement"); + }); +}); diff --git a/packages/typescript/test/bansafe.test.ts b/packages/typescript/test/bansafe.test.ts new file mode 100644 index 0000000..2e668ed --- /dev/null +++ b/packages/typescript/test/bansafe.test.ts @@ -0,0 +1,223 @@ +import { afterEach, describe, expect, expectTypeOf, it } from "vitest"; + +import { + BanSafeResource, + Client, + type ApiResponse, + type BanSafeCollectionEnvelope, + type BanSafeHealthActionsEnvelope, + type BanSafeHealthBand, + type BanSafeHealthEnvelope, + type BanSafeHealthHistory, + type BanSafeHealthPoint, + type BanSafeSignalDefinition, + type BanSafeTelemetryDetail, + type BanSafeTelemetryHistoryEnvelope, + type DataEnvelope, + type ProjectHealthPolicy, +} from "../src/index.js"; +import { ORGANIZATION_API_KEY } from "./support/credentials.js"; +import { + startTestServer, + type RecordedRequest, + type TestServer, +} from "./support/http-server.js"; + +const servers: TestServer[] = []; + +afterEach(async () => { + await Promise.all(servers.splice(0).map((server) => server.close())); +}); + +async function testClient(): Promise<{ + client: Client; + requests: RecordedRequest[]; +}> { + const server = await startTestServer(() => ({ + headers: { "content-type": "application/json" }, + body: '{"data":[],"page":{"nextCursor":null,"hasMore":false}}', + })); + servers.push(server); + return { + client: new Client({ + credential: { + type: "organizationApiKey", + value: ORGANIZATION_API_KEY, + }, + baseUrl: server.url, + maxNetworkRetries: 0, + }), + requests: server.requests, + }; +} + +describe("Client BanSafe resources", () => { + it("exposes typed Health and telemetry reads without dashboard-only mutations", async () => { + const { client, requests } = await testClient(); + expectTypeOf(client.banSafe).toEqualTypeOf(); + expect(client.banSafe).not.toHaveProperty("acknowledgeFinding"); + expect(client.banSafe).not.toHaveProperty("appealEnforcement"); + + const health = await client.banSafe.listHealth({ + projectId: "project/a", + cursor: "cursor/a", + limit: 25, + }); + const detail = await client.banSafe.getHealth("session/a"); + const history = await client.banSafe.listHealthHistory("session/a", { + since: "2026-09-07T00:00:00.000Z", + limit: 12, + }); + const signals = await client.banSafe.listSignals(); + const telemetry = await client.banSafe.getTelemetry("session/a"); + const telemetryHistory = await client.banSafe.listTelemetryHistory( + "session/a", + { + since: "2026-09-07T00:00:00.000Z", + until: "2026-09-08T00:00:00.000Z", + cursor: "cursor/b", + limit: 10, + }, + ); + const collection = await client.banSafe.listCollection({ + projectId: "project/a", + cursor: "cursor/c", + limit: 25, + }); + const actions = await client.banSafe.listHealthActions({ + projectId: "project/a", + session: "session/a", + status: "succeeded", + cursor: "cursor/d", + limit: 25, + }); + + expectTypeOf(health).toEqualTypeOf>(); + expectTypeOf(detail.data.data).toHaveProperty("healthEstimatorVersion"); + expectTypeOf(history).toEqualTypeOf< + ApiResponse> + >(); + expectTypeOf< + BanSafeHealthPoint["band"] + >().toEqualTypeOf(); + expectTypeOf(signals).toEqualTypeOf< + ApiResponse> + >(); + expectTypeOf(telemetry).toEqualTypeOf< + ApiResponse> + >(); + expectTypeOf(telemetryHistory).toEqualTypeOf< + ApiResponse + >(); + expectTypeOf(collection).toEqualTypeOf< + ApiResponse + >(); + expectTypeOf(actions).toEqualTypeOf< + ApiResponse + >(); + expect(requests.map(({ method, path }) => `${method} ${path}`)).toEqual([ + "GET /platform/bansafe/health?projectId=project%2Fa&cursor=cursor%2Fa&limit=25", + "GET /platform/bansafe/health/session%2Fa", + "GET /platform/bansafe/health/session%2Fa/history?since=2026-09-07T00%3A00%3A00.000Z&limit=12", + "GET /platform/bansafe/signals", + "GET /platform/bansafe/telemetry/session%2Fa", + "GET /platform/bansafe/telemetry/session%2Fa/history?since=2026-09-07T00%3A00%3A00.000Z&until=2026-09-08T00%3A00%3A00.000Z&cursor=cursor%2Fb&limit=10", + "GET /platform/bansafe/collection?projectId=project%2Fa&cursor=cursor%2Fc&limit=25", + "GET /platform/bansafe/health-actions?projectId=project%2Fa&session=session%2Fa&status=succeeded&cursor=cursor%2Fd&limit=25", + ]); + }); + + it("maps API-key-authorized findings, enforcement, incidents, and claims", async () => { + const { client, requests } = await testClient(); + await client.banSafe.listFindings({ + projectId: "project/a", + session: "session/a", + status: "open", + severity: "critical", + limit: 5, + }); + await client.banSafe.listEnforcement({ + projectId: "project/a", + rung: "throttle", + }); + await client.banSafe.listIncidents({ + projectId: "project/a", + session: "session/a", + }); + await client.banSafe.createIncident( + { + session: "session/a", + occurredAt: "2026-09-08T00:00:00.000Z", + note: "WhatsApp restricted sending", + }, + { idempotencyKey: "incident/a" }, + ); + await client.banSafe.retractIncident("incident/a"); + await client.banSafe.listClaims({ + projectId: "project/a", + session: "session/a", + status: "under_review", + }); + await client.banSafe.getClaim("claim/a"); + + expect(requests.map(({ method, path }) => `${method} ${path}`)).toEqual([ + "GET /platform/bansafe/findings?projectId=project%2Fa&session=session%2Fa&status=open&severity=critical&limit=5", + "GET /platform/bansafe/enforcement?projectId=project%2Fa&rung=throttle", + "GET /platform/bansafe/incidents?projectId=project%2Fa&session=session%2Fa", + "POST /platform/bansafe/incidents", + "POST /platform/bansafe/incidents/incident%2Fa/retract", + "GET /platform/bansafe/claims?projectId=project%2Fa&session=session%2Fa&status=under_review", + "GET /platform/bansafe/claims/claim%2Fa", + ]); + expect(requests[3]?.headers["idempotency-key"]).toBe("incident/a"); + expect(JSON.parse(requests[3]!.body)).toEqual({ + session: "session/a", + occurredAt: "2026-09-08T00:00:00.000Z", + note: "WhatsApp restricted sending", + }); + }); + + it("maps project and session safety settings to their typed owners", async () => { + const { client, requests } = await testClient(); + await client.projects.getSafeMode("project/a"); + await client.projects.updateSafeMode("project/a", { pacing: "jittered" }); + await client.projects.getWarmupPlan("project/a"); + await client.projects.updateWarmupPlan("project/a", { + enabled: true, + warmupDays: 30, + dailyStart: 20, + }); + await client.projects.getInsuranceEvidence("project/a"); + await client.projects.updateInsuranceEvidence("project/a", { + enabled: true, + }); + const policy = await client.projects.getHealthPolicy("project/a"); + await client.projects.updateHealthPolicy("project/a", { + version: 4, + enabled: true, + threshold: 50, + sessionAction: "slow_down", + slowDownMps: 0.5, + emailNotification: true, + webhookNotification: true, + }); + await client.sessions.getSafeMode("session/a"); + await client.sessions.updateSafeMode("session/a", { typing: "inherit" }); + + expectTypeOf(policy).toEqualTypeOf< + ApiResponse> + >(); + expect(requests.map(({ method, path }) => `${method} ${path}`)).toEqual([ + "GET /platform/projects/project%2Fa/safe-mode", + "PUT /platform/projects/project%2Fa/safe-mode", + "GET /platform/projects/project%2Fa/warmup-plan", + "PUT /platform/projects/project%2Fa/warmup-plan", + "GET /platform/projects/project%2Fa/insurance-evidence", + "PUT /platform/projects/project%2Fa/insurance-evidence", + "GET /platform/projects/project%2Fa/health-policy", + "PUT /platform/projects/project%2Fa/health-policy", + "GET /platform/sessions/session%2Fa/safe-mode", + "PUT /platform/sessions/session%2Fa/safe-mode", + ]); + }); +}); diff --git a/packages/typescript/test/business.test.ts b/packages/typescript/test/business.test.ts index 1210ba8..3ca6968 100644 --- a/packages/typescript/test/business.test.ts +++ b/packages/typescript/test/business.test.ts @@ -118,7 +118,11 @@ describe("MessagingClient business", () => { expect( requests.map(({ method, path, body }) => ({ method, path, body })), ).toEqual([ - { method: "GET", path: "/messaging/sales%2Feu/business/profile", body: "" }, + { + method: "GET", + path: "/messaging/sales%2Feu/business/profile", + body: "", + }, { method: "PATCH", path: "/messaging/sales%2Feu/business/profile", diff --git a/packages/typescript/test/coverage-issues.test.ts b/packages/typescript/test/coverage-issues.test.ts index be35bd9..b7bb9b5 100644 --- a/packages/typescript/test/coverage-issues.test.ts +++ b/packages/typescript/test/coverage-issues.test.ts @@ -63,7 +63,12 @@ async function runScript( describe("coverage issue synchronizer", () => { it("creates the label, reopens and updates matches, creates new gaps, and closes resolved issues", async () => { const requests: RecordedRequest[] = []; - const existingMarker = marker("dev", "messaging", "GET", "/messaging/sessions"); + const existingMarker = marker( + "dev", + "messaging", + "GET", + "/messaging/sessions", + ); const staleMarker = marker("dev", "platform", "GET", "/platform/old"); const server = await startTestServer((request) => { requests.push(request); diff --git a/packages/typescript/test/system.test.ts b/packages/typescript/test/system.test.ts index 7f434b6..7370fff 100644 --- a/packages/typescript/test/system.test.ts +++ b/packages/typescript/test/system.test.ts @@ -51,7 +51,12 @@ describe("SystemClient", () => { expectTypeOf(ping).toEqualTypeOf>(); expect( fetch.mock.calls.map(([input]) => new URL(String(input)).pathname), - ).toEqual(["/messaging/info/status", "/messaging/info/version", "/health", "/ping"]); + ).toEqual([ + "/messaging/info/status", + "/messaging/info/version", + "/health", + "/ping", + ]); for (const [, init] of fetch.mock.calls) { expect(new Headers(init?.headers).has("authorization")).toBe(false); } diff --git a/packages/typescript/test/transport.test.ts b/packages/typescript/test/transport.test.ts index a65a5fc..827f921 100644 --- a/packages/typescript/test/transport.test.ts +++ b/packages/typescript/test/transport.test.ts @@ -163,7 +163,7 @@ describe("HttpTransport", () => { "content-type": "application/json", "x-request-id": "req_auth", }, - body: '{"error":"bad key","code":"invalid_key"}', + body: '{"error":{"type":"authentication_error","code":"invalid_credential","message":"Supply a valid credential.","param":null},"data":null,"docs":"https://docs.polymorfa.com/api/errors#invalid-credential"}', }; } return { @@ -172,7 +172,7 @@ describe("HttpTransport", () => { "content-type": "application/json", "x-request-id": "req_validation", }, - body: '{"error":"invalid project"}', + body: '{"error":{"type":"invalid_request_error","code":"invalid_parameter","message":"Correct the invalid project field.","param":"projectId"},"data":null,"docs":"https://docs.polymorfa.com/api/errors#invalid-parameter"}', }; }); const transport = makeTransport(server.url); @@ -184,7 +184,18 @@ describe("HttpTransport", () => { expect(authError).toMatchObject({ status: 401, requestId: "req_auth", - code: "invalid_key", + code: "invalid_credential", + message: "Supply a valid credential.", + details: { + error: { + type: "authentication_error", + code: "invalid_credential", + message: "Supply a valid credential.", + param: null, + }, + data: null, + docs: "https://docs.polymorfa.com/api/errors#invalid-credential", + }, }); const validationError = await transport @@ -194,6 +205,8 @@ describe("HttpTransport", () => { expect(validationError).toMatchObject({ status: 400, requestId: "req_validation", + code: "invalid_parameter", + message: "Correct the invalid project field.", }); });