{
  "openapi": "3.1.0",
  "info": {
    "title": "Teloring API",
    "version": "1.0.0",
    "summary": "Automate everything the Teloring console can do, from your own systems.",
    "description": "The Teloring REST API gives your own systems the same reach an agent has in\nthe console: conversations across every channel, the CRM behind them, the\nautomations, the knowledge bases, the numbers, and — when you need it —\na way to drop one of your users straight into a specific chat.\n\n## Base URL\n\n```\nhttps://api.teloring.com/v1\n```\n\nEvery path in this reference is relative to that. There is no account id in\nany path: your access token already identifies the account, which is what\nmakes it impossible for a credential to reach somebody else's data.\n\n## Getting started in four steps\n\n1. In the console, go to **Settings → API** and create a credential. Choose\n   its scopes — each one unlocks a whole feature area — and copy the\n   **client secret**. It is shown once and never again.\n2. Exchange the client id and secret for an access token:\n   `POST /v1/oauth/token`. Tokens last one hour.\n3. Send the token as `Authorization: Bearer <access_token>` on every\n   request.\n4. Call `GET /v1/oauth/introspect` if anything is unexpected — it tells you\n   which account you are on and exactly which scopes you hold.\n\n## What you should know before you build\n\n- **Server-side only.** There are no CORS headers on this API by design. A\n  token in browser JavaScript is a token in your page source.\n- **Scopes are checked live.** Removing a scope in the console takes effect\n  on the very next request, not when the token expires.\n- **Some calls cost money.** Creating an agent takes a seat and may charge\n  the card on file. WhatsApp templates, outbound SMS and signing links cost\n  credits. Each of those endpoints says so.\n- **Rate limit:** 600 requests per minute per credential; 20 per minute per\n  IP on the token endpoint. Cache your token — you need one per hour, not\n  one per request.\n- **IP restrictions apply here too.** If the account has an IP allow-list\n  set under Settings → Security & login, it governs API calls exactly as it\n  governs sign-in. Calling from an address that is not on it answers `403`\n  with `code: ip_not_allowed` — add your server's outbound IP there.\n\n## Errors\n\nEvery failure answers in the same shape, with a machine-readable `code` and\na `request_id` to quote if you need help:\n\n```json\n{\n  \"error\": {\n    \"type\": \"invalid_request_error\",\n    \"code\": \"missing_parameter\",\n    \"message\": \"'inbox_id' is required.\",\n    \"param\": \"inbox_id\",\n    \"request_id\": \"req_5f2a91c0e8b74d3a9c1e\"\n  }\n}\n```\n",
    "contact": {
      "name": "Teloring support",
      "url": "https://docs.teloring.com"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://teloring.com"
    }
  },
  "servers": [
    {
      "url": "https://api.teloring.com/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Authentication",
      "description": "Turning a client id and secret into a one-hour access token.\n\nThis is the only unauthenticated endpoint in the API, and the only one\nthat reads your client secret. Cache the token you get back and re-request\nit when it expires or when a call answers `401`.\n\nIf the account restricts access by IP (Settings → Security & login), that\nrestriction is enforced here as well — a call from an address that is not\non the list is refused before any token is issued.\n"
    },
    {
      "name": "Conversations",
      "description": "The threads between a contact and the business, across every channel.\n\n**Scope:** `conversations`\n\nA conversation belongs to an **inbox** (the channel it arrived on) and a\n**contact** (the person on the other end). Its `status` moves between\n`open`, `pending`, `on_hold` and `resolved`; `on_hold` additionally\ncarries a deadline and is set through its own endpoint.\n"
    },
    {
      "name": "Messages",
      "description": "Reading and sending inside a conversation.\n\n**Scope:** `messages`\n\nChannels are not interchangeable here. WhatsApp closes a 24-hour window\nafter the customer's last message, after which only approved templates\nmay be sent; TikTok has a 48-hour window and a per-window message cap;\nvoice conversations accept private notes only. Each rule is enforced\nbefore the send, with a specific error `code`, rather than surfaced as a\nprovider failure afterwards.\n"
    },
    {
      "name": "Customers",
      "description": "The business records contacts belong to.\n\n**Scope:** `customers`\n\nA **contact** is a channel identity — this phone number on WhatsApp, this\nemail address. A **customer** is the company or household those identities\nbelong to. One customer owns many contacts; a conversation belongs to a\ncontact, and through it to a customer.\n"
    },
    {
      "name": "Customer objects",
      "description": "The mini-CRM: object types and the records filed under each customer.\n\n**Scope:** `customer_objects`\n\nAn **object** is a type — Contacts, Deals, Service Calls, Tasks, plus\nwhatever was defined in the field editor. A **record** is one instance,\nand every record belongs to exactly one customer. Records can be read\nper-customer, or account-wide across every customer.\n"
    },
    {
      "name": "Analytics",
      "description": "Dashboards and the graphs on them.\n\n**Scope:** `analytics`\n\nGraph values are computed on demand, not stored. Fetching them is opt-in\n(`?include=values`) because it is genuinely expensive — cache the result\nrather than polling.\n"
    },
    {
      "name": "Studio",
      "description": "The automations built on the Studio canvas. Read-only.\n\n**Scope:** `studio`\n\nA flow is a graph of blocks at coordinates, wired through named handles.\nThis API lets you see which flows exist, whether they are live, and how\nevery block is configured. Editing a flow is a visual act and stays in\nthe console.\n"
    },
    {
      "name": "AI World",
      "description": "Which AI capabilities are switched on for the account.\n\n**Scope:** `ai_world`\n\nEach item is a plain on/off. Most of them consume AI credits when they\nrun, so treat enabling one as a deliberate act.\n"
    },
    {
      "name": "Knowledge base",
      "description": "The documents the AI is allowed to answer from.\n\n**Scope:** `knowledge_base`\n\nA knowledge base holds **sources** (a file, or a crawled URL), and each\nsource is split into **chunks** — the passages the retriever matches a\nquestion against. Ingestion is asynchronous: add a source, then poll until\nits status reads `ready`.\n"
    },
    {
      "name": "Quick replies",
      "description": "Saved snippets agents insert into a conversation.\n\n**Scope:** `quick_replies`\n\n`account` replies are shared with everyone; `personal` ones belong to a\nsingle agent and are addressed by `agent_id`.\n"
    },
    {
      "name": "Forms",
      "description": "Forms and their submissions. Read and delete.\n\n**Scope:** `forms`\n\nBuilding a form is a visual act with no honest JSON equivalent, so it\nstays in the console. Pulling submissions into another system is what this\nAPI is for.\n"
    },
    {
      "name": "Document signature",
      "description": "Documents sent out for signature, and the links people sign them through.\n\n**Scope:** `documents_signature`\n\nA **document** is an uploaded PDF; it becomes signable once signature\nfields are placed in the console's editor. A **signing link** is one\nrecipient's invitation to sign one document, and **costs credits**.\n"
    },
    {
      "name": "Account",
      "description": "Who this business is, and when it is open.\n\n**Scopes:** `account`, `business_hours`, `conversation_attributes`\n\nAn Israeli account's `billing_country` is locked once billing starts: it\ndetermined the VAT on invoices already issued.\n"
    },
    {
      "name": "Agents & teams",
      "description": "The people — and the AI — who answer conversations.\n\n**Scope:** `agents_teams`\n\n⚠️ **Creating an agent can charge the card on file.** A human or AI agent\noccupies a seat; if the plan has none free, a prorated charge is taken.\nA `402` with `code: seat_charge_failed` means nothing was created and a\nretry is safe.\n"
    },
    {
      "name": "Audit log",
      "description": "Who did what, including what this API did.\n\n**Scope:** `audit_log`\n\nRead-only by design. Every write made through this API is recorded with\n`details.via = \"public_api\"` and the credential's client id, so an\nAPI-driven change is never anonymous.\n"
    },
    {
      "name": "Billing",
      "description": "Credits, the price list they are spent against, and invoices. Read-only.\n\n**Scope:** `billing`\n\nNothing here can spend money or change a plan. Two balances exist and are\nnot interchangeable: `monthly` (included, resets each period, does not\nroll over) and `topup` (bought, spent only once monthly runs out).\n"
    },
    {
      "name": "Files",
      "description": "Every file that passed through the account, and how much space it uses.\n\n**Scope:** `files`\n\nDeleting is destructive: the stored object is removed and a message that\nreferenced it shows a broken attachment afterwards.\n"
    },
    {
      "name": "Profile",
      "description": "One agent's personal settings and notification preferences.\n\n**Scope:** `profile`\n\nEmail and password cannot be changed here. Both are identity rather than\nprofile: an email change must be confirmed from the address itself, and a\npassword can only be set by the person who owns it.\n"
    },
    {
      "name": "Notifications",
      "description": "An agent's bell feed.\n\n**Scope:** `notifications`\n\nRead-only, and deliberately non-destructive: reading the feed here does\nnot clear the badge a human has not looked at yet.\n"
    },
    {
      "name": "SSO",
      "description": "Signing one of your agents straight into the console from your own system.\n\n**Scope:** `sso`\n\nThe most powerful thing in this API, and the most tightly controlled. The\nscope alone grants nothing: the credential must also name the agents it\nmay impersonate, and (for iframe embedding) the origins allowed to frame\nthe session. Links expire in ten minutes and work exactly once.\n"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "`Authorization: Bearer <access_token>`, where the token came from\n`POST /v1/oauth/token`. Tokens last one hour. A `401` with\n`code: invalid_token` means fetch a new one.\n"
      }
    },
    "parameters": {
      "Page": {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "1-based page number.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "PerPage": {
        "name": "per_page",
        "in": "query",
        "required": false,
        "description": "Items per page. A value outside the range is a `400`, not a silent clamp.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        }
      },
      "SortDir": {
        "name": "sort_dir",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "default": "desc"
        }
      },
      "CreatedAfter": {
        "name": "created_after",
        "in": "query",
        "required": false,
        "description": "ISO-8601 timestamp. Only items created at or after this moment.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "CreatedBefore": {
        "name": "created_before",
        "in": "query",
        "required": false,
        "description": "ISO-8601 timestamp. Only items created strictly before this moment.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "ConversationId": {
        "name": "conversation_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "CustomerId": {
        "name": "customer_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "AgentId": {
        "name": "agent_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "ObjectId": {
        "name": "object_id",
        "in": "path",
        "required": true,
        "description": "The object type's id, from `GET /v1/objects`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "RequestId": {
        "description": "Correlation id for this request. Quote it when reporting a problem.",
        "schema": {
          "type": "string",
          "example": "req_5f2a91c0e8b74d3a9c1e"
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string",
                "description": "The family of failure, so one handler can cover a class of them.",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "permission_error",
                  "not_found_error",
                  "conflict_error",
                  "plan_limit_error",
                  "rate_limit_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string",
                "description": "The specific problem, stable across releases.",
                "example": "missing_parameter"
              },
              "message": {
                "type": "string",
                "description": "A sentence written for the developer reading it."
              },
              "param": {
                "type": "string",
                "description": "The offending field, when one can be named."
              },
              "details": {
                "type": "object",
                "additionalProperties": true,
                "description": "Extra structure — per-field validation errors, granted scopes, plan limits."
              },
              "request_id": {
                "type": "string"
              }
            }
          }
        }
      },
      "PageMeta": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "count": {
            "type": "integer",
            "description": "Items on this page."
          },
          "total": {
            "type": "integer",
            "description": "Total across all pages. Omitted where counting would cost a second full scan."
          },
          "total_pages": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean",
            "description": "Always present. This is what a paging loop should test."
          }
        }
      },
      "DeletedResource": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        }
      },
      "AccessToken": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "token_type": {
            "type": "string",
            "enum": [
              "Bearer"
            ]
          },
          "expires_in": {
            "type": "integer",
            "example": 3600,
            "description": "Seconds until expiry."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What this credential holds. Informational — authorization is re-read from the credential on every request."
          },
          "account_id": {
            "type": "string"
          }
        }
      },
      "TokenIntrospection": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "token_introspection"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "account_id": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          },
          "credential_id": {
            "type": "string"
          },
          "credential_name": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "credential_expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "sso_agent_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Only populated when the credential holds the `sso` scope."
          },
          "sso_origins": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "request_id": {
            "type": "string"
          }
        }
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "conversation"
            ]
          },
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "missed",
              "pending",
              "on_hold",
              "resolved"
            ]
          },
          "inbox_id": {
            "type": "string"
          },
          "inbox_type": {
            "type": "string",
            "description": "The channel family.",
            "example": "whatsapp"
          },
          "inbox_name": {
            "type": "string"
          },
          "contact_id": {
            "type": "string"
          },
          "contact": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "email": {
                "type": "string"
              }
            }
          },
          "customer_id": {
            "type": "string"
          },
          "assignee_id": {
            "type": "string",
            "description": "The agent who owns it, or an empty string."
          },
          "assignee_name": {
            "type": "string"
          },
          "team_id": {
            "type": "string"
          },
          "team_name": {
            "type": "string"
          },
          "subject": {
            "type": "string"
          },
          "priority": {
            "type": "string",
            "enum": [
              "",
              "low",
              "medium",
              "high",
              "urgent"
            ]
          },
          "flag": {
            "type": "string",
            "description": "One of the flag emoji: 🔴 🟡 🟢 🔵"
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pinned": {
            "type": "boolean"
          },
          "unread_count": {
            "type": "integer"
          },
          "message_count": {
            "type": "integer"
          },
          "last_message_preview": {
            "type": "string"
          },
          "last_message_direction": {
            "type": "string",
            "enum": [
              "",
              "incoming",
              "outgoing"
            ]
          },
          "last_message_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resolved_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "on_hold_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "custom_attributes": {
            "type": "object",
            "additionalProperties": true,
            "description": "Only on single-conversation responses."
          },
          "studio_flow_id": {
            "type": "string",
            "description": "Set while a Studio flow owns the conversation."
          },
          "ai_session_id": {
            "type": "string",
            "description": "Set while an AI agent is handling it."
          },
          "first_response_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resolved_by": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "ConversationCounts": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "conversation_counts"
            ]
          },
          "all_open": {
            "type": "integer",
            "description": "Every open conversation, however it is owned."
          },
          "assigned": {
            "type": "integer",
            "description": "Open and owned by a human agent."
          },
          "waiting": {
            "type": "integer",
            "description": "Open with no owner — the waiting line."
          },
          "studio_bot": {
            "type": "integer",
            "description": "Currently driven by a Studio flow."
          },
          "ai_agent": {
            "type": "integer",
            "description": "Currently handled by an AI agent."
          },
          "on_hold": {
            "type": "integer"
          },
          "pending": {
            "type": "integer"
          },
          "resolved": {
            "type": "integer"
          }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "message"
            ]
          },
          "id": {
            "type": "string"
          },
          "conversation_id": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "The text, or the media URL for a media message."
          },
          "content_type": {
            "type": "string",
            "enum": [
              "text",
              "image",
              "video",
              "audio",
              "document",
              "sticker",
              "location"
            ]
          },
          "caption": {
            "type": "string"
          },
          "direction": {
            "type": "string",
            "enum": [
              "incoming",
              "outgoing"
            ]
          },
          "private": {
            "type": "boolean",
            "description": "An internal note. Never delivered to the customer."
          },
          "status": {
            "type": "string",
            "description": "pending → sent → delivered → read, as far as the channel reports."
          },
          "sender_type": {
            "type": "string",
            "enum": [
              "agent",
              "contact",
              "system",
              "bot"
            ]
          },
          "sender_id": {
            "type": "string"
          },
          "sender_name": {
            "type": "string"
          },
          "inbox_type": {
            "type": "string"
          },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "reply_to_message_id": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Inbox": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "inbox"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "whatsapp, sms, email, live_chat, api, telegram, line, voice, facebook_page, facebook_messenger, instagram, instagram_dm, tiktok_messenger.\n"
          },
          "active": {
            "type": "boolean"
          },
          "identifier": {
            "type": "string",
            "description": "The phone number, email address or handle this inbox answers on."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WhatsAppTemplate": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "whatsapp_template"
            ]
          },
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "utility",
              "marketing",
              "authentication"
            ]
          },
          "status": {
            "type": "string",
            "description": "Only `approved` templates can be sent."
          },
          "body": {
            "type": "string"
          },
          "header_type": {
            "type": "string"
          },
          "body_variable_count": {
            "type": "integer",
            "description": "How many values `template.body_variables` must carry."
          }
        }
      },
      "Customer": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "customer"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "industry": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "logo_url": {
            "type": "string"
          },
          "assigned_agent": {
            "type": "string"
          },
          "lifecycle_stage": {
            "type": "string",
            "description": "One of the account's configured stages, e.g. `lead`, `customer`."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "contacts": {
            "type": "array",
            "description": "Only when requested with `?include=contacts`.",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_by": {
            "type": "string"
          }
        }
      },
      "Contact": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "contact"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "inbox_type": {
            "type": "string"
          },
          "inbox_id": {
            "type": "string"
          },
          "avatar_url": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CustomerObject": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "customer_object"
            ]
          },
          "id": {
            "type": "string",
            "example": "deals"
          },
          "label": {
            "type": "string"
          },
          "label_singular": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "is_default": {
            "type": "boolean"
          },
          "position": {
            "type": "integer",
            "nullable": true
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "description": "The key to use inside a record's `data`."
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "example": "select"
                },
                "required": {
                  "type": "boolean"
                },
                "options": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "is_system": {
                  "type": "boolean"
                }
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CustomerObjectRecord": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "customer_object_record"
            ]
          },
          "id": {
            "type": "string"
          },
          "object_id": {
            "type": "string"
          },
          "customer_id": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Field values, keyed by the object's `fields[].key`."
          },
          "links": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_by": {
            "type": "string"
          },
          "updated_by": {
            "type": "string"
          }
        }
      },
      "Dashboard": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "dashboard"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "is_default": {
            "type": "boolean",
            "description": "The dashboard Teloring seeds for a new account."
          },
          "tabs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "order": {
                  "type": "integer"
                }
              }
            }
          },
          "graphs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Graph"
            }
          },
          "values_included": {
            "type": "boolean"
          },
          "values_truncated_after": {
            "type": "integer",
            "description": "Present when the dashboard has more graphs than one call will compute."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Graph": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "graph"
            ]
          },
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "tab_id": {
            "type": "string"
          },
          "chart_type": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "metric": {
            "type": "string"
          },
          "group_by": {
            "type": "string"
          },
          "date_range": {
            "type": "object",
            "additionalProperties": true
          },
          "filters": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "position": {
            "type": "object",
            "additionalProperties": true
          },
          "value": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "The computed result. Only when requested with `?include=values`."
          }
        }
      },
      "StudioFlow": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "studio_flow"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "live",
              "paused",
              "disabled"
            ]
          },
          "version": {
            "type": "integer"
          },
          "node_count": {
            "type": "integer"
          },
          "trigger_count": {
            "type": "integer"
          },
          "has_unpublished_changes": {
            "type": "boolean"
          },
          "disabled_reason": {
            "type": "string"
          },
          "broken_dependencies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudioBlock"
            }
          },
          "connections": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "from_block_id": {
                  "type": "string"
                },
                "from_handle": {
                  "type": "string",
                  "description": "Which output the edge leaves by — this is what identifies a branch."
                },
                "to_block_id": {
                  "type": "string"
                },
                "to_handle": {
                  "type": "string"
                }
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_by": {
            "type": "string"
          },
          "last_edited_by": {
            "type": "string"
          }
        }
      },
      "StudioBlock": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "studio_block"
            ]
          },
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "example": "action.send_whatsapp_template"
          },
          "kind": {
            "type": "string",
            "enum": [
              "trigger",
              "action"
            ]
          },
          "label": {
            "type": "string"
          },
          "settings": {
            "type": "object",
            "additionalProperties": true,
            "description": "Block-specific. `GET /v1/studio/blocks` describes each shape."
          },
          "position": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "AiFeature": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "ai_feature"
            ]
          },
          "key": {
            "type": "string",
            "example": "ai_copilot"
          },
          "label": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "changed": {
            "type": "boolean",
            "description": "On a PUT, whether this call actually changed anything."
          }
        }
      },
      "KnowledgeBase": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "knowledge_base"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "source_count": {
            "type": "integer",
            "nullable": true
          },
          "chunk_count": {
            "type": "integer",
            "nullable": true
          },
          "stats": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "KnowledgeBaseSource": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "knowledge_base_source"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "file",
              "url"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "ready",
              "failed"
            ],
            "description": "Poll until `ready`. Ingestion is asynchronous."
          },
          "chunk_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "KnowledgeBaseChunk": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "knowledge_base_chunk"
            ]
          },
          "id": {
            "type": "string"
          },
          "source_id": {
            "type": "string"
          },
          "source_name": {
            "type": "string"
          },
          "chunk_type": {
            "type": "string",
            "enum": [
              "text",
              "image"
            ]
          },
          "page_number": {
            "type": "integer",
            "nullable": true
          },
          "chunk_index": {
            "type": "integer"
          },
          "model": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "description": "The indexed passage. Image chunks report a placeholder rather than megabytes of base64."
          },
          "content_length": {
            "type": "integer"
          }
        }
      },
      "QuickReply": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "quick_reply"
            ]
          },
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string",
            "description": "May contain merge variables such as {{contact.name}}, resolved when an agent inserts it."
          },
          "scope": {
            "type": "string",
            "enum": [
              "account",
              "personal"
            ]
          },
          "category_id": {
            "type": "string"
          },
          "category_name": {
            "type": "string"
          },
          "owner_agent_id": {
            "type": "string",
            "description": "Set only for `personal` replies."
          },
          "created_by": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Form": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "form"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "public_url": {
            "type": "string"
          },
          "submission_count": {
            "type": "integer"
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "settings": {
            "type": "object",
            "additionalProperties": true
          },
          "fields": {
            "type": "array",
            "description": "Only on the single-form response.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "The key each answer is stored under."
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "required": {
                  "type": "boolean"
                },
                "placeholder": {
                  "type": "string"
                },
                "help_text": {
                  "type": "string"
                },
                "options": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "FormSubmission": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "form_submission"
            ]
          },
          "id": {
            "type": "string"
          },
          "form_id": {
            "type": "string"
          },
          "form_name": {
            "type": "string"
          },
          "form_version": {
            "type": "integer",
            "nullable": true
          },
          "contact_id": {
            "type": "string"
          },
          "conversation_id": {
            "type": "string"
          },
          "answers": {
            "type": "object",
            "additionalProperties": true,
            "description": "Flat `{field_id: value}` — what most integrations want."
          },
          "answers_detail": {
            "type": "array",
            "description": "The same answers with their label and type, for rendering without also fetching the form.",
            "items": {
              "type": "object",
              "properties": {
                "field_id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "value": {}
              }
            }
          },
          "hidden_values": {
            "type": "object",
            "additionalProperties": true
          },
          "source_params": {
            "type": "object",
            "additionalProperties": true
          },
          "user_agent": {
            "type": "string"
          },
          "completion_time_ms": {
            "type": "integer",
            "nullable": true
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "SignatureDocument": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "signature_document"
            ]
          },
          "id": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active"
            ],
            "description": "`draft` until signature fields are placed in the console's editor. Only `active` documents can be sent for signature.\n"
          },
          "page_count": {
            "type": "integer"
          },
          "field_count": {
            "type": "integer"
          },
          "file_size_mb": {
            "type": "number",
            "nullable": true
          },
          "language": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_by": {
            "type": "string"
          }
        }
      },
      "SigningLink": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "signing_link"
            ]
          },
          "id": {
            "type": "string"
          },
          "document_id": {
            "type": "string"
          },
          "document_name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "signed",
              "declined",
              "expired"
            ]
          },
          "signing_url": {
            "type": "string",
            "description": "The URL to send the recipient."
          },
          "customer_id": {
            "type": "string"
          },
          "customer_name": {
            "type": "string"
          },
          "contact_id": {
            "type": "string"
          },
          "contact_name": {
            "type": "string"
          },
          "conversation_id": {
            "type": "string"
          },
          "custom_attributes": {
            "type": "object",
            "additionalProperties": true
          },
          "created": {
            "type": "boolean",
            "description": "`false` means an existing link was returned and nothing was charged."
          },
          "opened_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "signed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "SignedDocument": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "signed_document"
            ]
          },
          "id": {
            "type": "string"
          },
          "document_id": {
            "type": "string"
          },
          "document_name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "declined"
            ]
          },
          "customer_id": {
            "type": "string"
          },
          "customer_name": {
            "type": "string"
          },
          "contact_id": {
            "type": "string"
          },
          "contact_name": {
            "type": "string"
          },
          "signer_name": {
            "type": "string"
          },
          "signer_email": {
            "type": "string"
          },
          "decline_reason": {
            "type": "string"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "account"
            ]
          },
          "id": {
            "type": "string"
          },
          "business_name": {
            "type": "string"
          },
          "industry": {
            "type": "string"
          },
          "contact_email": {
            "type": "string"
          },
          "contact_phone": {
            "type": "string"
          },
          "default_language": {
            "type": "string",
            "enum": [
              "en",
              "he"
            ]
          },
          "timezone": {
            "type": "string",
            "example": "Asia/Jerusalem"
          },
          "default_currency": {
            "type": "string",
            "example": "ILS"
          },
          "logo_url": {
            "type": "string"
          },
          "business_tax_id": {
            "type": "string"
          },
          "business_address": {
            "type": "string"
          },
          "business_city": {
            "type": "string"
          },
          "business_contact_name": {
            "type": "string"
          },
          "billing_country": {
            "type": "string",
            "example": "IL"
          },
          "billing_country_locked": {
            "type": "boolean",
            "description": "True once billing has started. Israeli accounts cannot be moved."
          },
          "plan": {
            "type": "string"
          },
          "owner_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "BusinessHours": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "business_hours"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "system": {
            "type": "boolean",
            "description": "System schedules cannot be edited or deleted."
          },
          "days": {
            "type": "object",
            "additionalProperties": true,
            "description": "Weekday → opening periods, e.g. {\"monday\": [{\"start\": \"09:00\", \"end\": \"17:00\"}]}. A day with no periods is closed."
          },
          "holiday_calendar_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "consider_holidays": {
            "type": "boolean"
          },
          "exceptions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "upcoming_holidays": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "HolidayCalendar": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "holiday_calendar"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "system": {
            "type": "boolean"
          },
          "year": {
            "type": "integer"
          },
          "dates": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "ConversationAttributeSchema": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "conversation_attribute_schema"
            ]
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "order": {
                  "type": "integer"
                }
              }
            }
          },
          "attributes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "type": "string",
                  "enum": [
                    "conversation_attribute"
                  ]
                },
                "api_id": {
                  "type": "string",
                  "description": "The key to use when writing values onto a conversation."
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "text",
                    "number",
                    "select",
                    "multi_select",
                    "date",
                    "checkbox",
                    "url",
                    "email"
                  ]
                },
                "section_id": {
                  "type": "string"
                },
                "required": {
                  "type": "boolean"
                },
                "options": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "order": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "ConversationCustomAttributes": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "conversation_custom_attributes"
            ]
          },
          "conversation_id": {
            "type": "string"
          },
          "values": {
            "type": "object",
            "additionalProperties": true
          },
          "attributes": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "Agent": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "agent"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "human",
              "ai"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "role_id": {
            "type": "string"
          },
          "role_name": {
            "type": "string"
          },
          "is_owner": {
            "type": "boolean"
          },
          "phone": {
            "type": "string"
          },
          "department": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "avatar_url": {
            "type": "string"
          },
          "two_factor_enabled": {
            "type": "boolean"
          },
          "profile_id": {
            "type": "string",
            "description": "For AI agents, the id of their AI profile."
          },
          "welcome_email_sent": {
            "type": "boolean"
          },
          "seat_charge": {
            "type": "object",
            "nullable": true,
            "description": "Present when creating this agent took a seat that had to be paid for.",
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_login_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "AiAgent": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "ai_agent"
            ]
          },
          "id": {
            "type": "string"
          },
          "agent_id": {
            "type": "string",
            "description": "The agent record this AI fronts — what you assign a conversation to."
          },
          "profile_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "persona": {
            "type": "string"
          },
          "instructions": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "knowledge_base_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "handoff": {
            "type": "object",
            "additionalProperties": true
          },
          "settings": {
            "type": "object",
            "additionalProperties": true
          },
          "seat_charge": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Team": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "team"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "agent_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "agent_count": {
            "type": "integer"
          },
          "auto_assign_online": {
            "type": "boolean",
            "description": "Assigning the team immediately hands the conversation to a random online member."
          },
          "humans_only": {
            "type": "boolean",
            "description": "Keeps AI agents out of the team entirely."
          },
          "members": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Role": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "role"
            ]
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "is_owner": {
            "type": "boolean"
          },
          "is_default": {
            "type": "boolean"
          }
        }
      },
      "AuditEntry": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "audit_entry"
            ]
          },
          "id": {
            "type": "string"
          },
          "action": {
            "type": "string",
            "example": "conversation.updated"
          },
          "agent_id": {
            "type": "string",
            "description": "For API-driven changes this reads `api:<credential_id>`."
          },
          "agent_name": {
            "type": "string"
          },
          "agent_email": {
            "type": "string"
          },
          "ip_address": {
            "type": "string"
          },
          "user_agent": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "description": "Includes `via`, `client_id` and `credential_name` for anything done through this API."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CreditBalance": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "credit_balance"
            ]
          },
          "monthly_balance": {
            "type": "number",
            "description": "What is left of this period's included credits. Does not roll over."
          },
          "monthly_limit": {
            "type": "number"
          },
          "last_reset_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "topup_balance": {
            "type": "number",
            "description": "Total across every unexpired top-up package."
          },
          "total_balance": {
            "type": "number"
          },
          "plan_id": {
            "type": "string"
          },
          "plan_name": {
            "type": "string"
          },
          "topup_packages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "type": "string",
                  "enum": [
                    "credit_topup"
                  ]
                },
                "id": {
                  "type": "string"
                },
                "balance": {
                  "type": "number",
                  "description": "What is left of this package."
                },
                "original_amount": {
                  "type": "number",
                  "description": "What was bought."
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "nullable": true
                }
              }
            }
          }
        }
      },
      "UsagePrice": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "usage_price"
            ]
          },
          "id": {
            "type": "string",
            "description": "Also the `usage_item_id` on a credit transaction, so costs reconcile."
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "cost": {
            "type": "number",
            "description": "Credits per unit."
          },
          "unit": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CreditTransaction": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "credit_transaction"
            ]
          },
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "deduction",
              "topup",
              "refund"
            ]
          },
          "cost": {
            "type": "number"
          },
          "deducted_from": {
            "type": "string",
            "enum": [
              "",
              "monthly",
              "topup",
              "mixed",
              "topup_added"
            ]
          },
          "monthly_deducted": {
            "type": "number"
          },
          "topup_deducted": {
            "type": "number"
          },
          "description": {
            "type": "string"
          },
          "usage_item_id": {
            "type": "string"
          },
          "reference_type": {
            "type": "string"
          },
          "reference_id": {
            "type": "string"
          },
          "agent_id": {
            "type": "string"
          },
          "refunded": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "refunded_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "invoice"
            ]
          },
          "id": {
            "type": "string"
          },
          "number": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "vat_amount": {
            "type": "number"
          },
          "total": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "issued_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "plan"
            ]
          },
          "name": {
            "type": "string"
          },
          "limits": {
            "type": "object",
            "additionalProperties": true,
            "description": "Ceilings on customers, inboxes, flows, forms, knowledge bases and views. `0` means unlimited."
          },
          "features": {
            "type": "object",
            "additionalProperties": true,
            "description": "Which capabilities the plan includes. A `402` elsewhere is explained by one of these."
          },
          "storage_quota_mb": {
            "type": "integer",
            "nullable": true
          },
          "analytics_history_days": {
            "type": "integer",
            "nullable": true,
            "description": "`0` means full history."
          }
        }
      },
      "File": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "file"
            ]
          },
          "id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "image",
              "video",
              "document",
              "audio"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "incoming",
              "outgoing",
              "internal"
            ]
          },
          "size_bytes": {
            "type": "integer",
            "nullable": true
          },
          "conversation_id": {
            "type": "string"
          },
          "contact_id": {
            "type": "string"
          },
          "message_id": {
            "type": "string"
          },
          "uploaded_by": {
            "type": "string"
          },
          "download_url": {
            "type": "string",
            "description": "Short-lived signed URL. Only on the single-file response."
          },
          "download_url_expires_in": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "FileStats": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "file_stats"
            ]
          },
          "total_files": {
            "type": "integer"
          },
          "total_bytes": {
            "type": "integer"
          },
          "total_mb": {
            "type": "number"
          },
          "quota_bytes": {
            "type": "integer",
            "nullable": true,
            "description": "`null` means the plan has no storage ceiling."
          },
          "quota_mb": {
            "type": "number",
            "nullable": true
          },
          "usage_percent": {
            "type": "number",
            "nullable": true
          },
          "by_category": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "AgentProfile": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "agent_profile"
            ]
          },
          "agent_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "description": "Read-only here. See the Profile tag."
          },
          "timezone": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "department": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "avatar_url": {
            "type": "string",
            "description": "An authenticated proxy path, not a public URL."
          },
          "avatar_updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "NotificationSettings": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "notification_settings"
            ]
          },
          "agent_id": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean",
            "description": "The master switch."
          },
          "channels": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            },
            "description": "sound / email / push / bell."
          },
          "events": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "sound": {
            "type": "string"
          },
          "available_channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "available_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "available_sounds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Notification": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "notification"
            ]
          },
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "meta": {
            "type": "object",
            "additionalProperties": true
          },
          "conversation_id": {
            "type": "string"
          },
          "is_unread": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "SsoLogin": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "sso_login"
            ]
          },
          "url": {
            "type": "string",
            "description": "Open this in a browser. Valid for ten minutes, once."
          },
          "mode": {
            "type": "string",
            "enum": [
              "full",
              "conversation"
            ]
          },
          "agent_id": {
            "type": "string"
          },
          "agent_name": {
            "type": "string"
          },
          "embed": {
            "type": "boolean"
          },
          "allowed_origins": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_in": {
            "type": "integer",
            "example": 600
          },
          "single_use": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "target": {
            "type": "object",
            "nullable": true,
            "description": "Present for `conversation` mode — the contact and, when one already exists, the conversation the link will open.",
            "properties": {
              "contact_id": {
                "type": "string"
              },
              "contact_name": {
                "type": "string"
              },
              "contact_phone": {
                "type": "string"
              },
              "contact_email": {
                "type": "string"
              },
              "inbox_id": {
                "type": "string"
              },
              "conversation_id": {
                "type": "string",
                "description": "Empty when no open conversation exists — the composer opens instead."
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request was malformed, or a parameter was rejected.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "missing_parameter",
                "message": "'inbox_id' is required.",
                "param": "inbox_id",
                "request_id": "req_5f2a91c0e8b74d3a9c1e"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "No token, an expired token, or a credential that has been revoked.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "invalid_token",
                "message": "The access token is invalid, expired, or its credential was revoked. Request a new token from POST /v1/oauth/token.",
                "request_id": "req_5f2a91c0e8b74d3a9c1e"
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Refused. Either the credential does not hold the scope this endpoint needs (`code: insufficient_scope`), or the account's IP allow-list does not include the calling address (`code: ip_not_allowed`).\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "permission_error",
                "code": "insufficient_scope",
                "message": "This credential does not hold the 'conversations' scope. Edit the credential in Settings → API to grant it.",
                "details": {
                  "required_scope": [
                    "conversations"
                  ],
                  "granted_scopes": [
                    "customers",
                    "billing"
                  ]
                },
                "request_id": "req_5f2a91c0e8b74d3a9c1e"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource in this account.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "The request was valid but conflicts with the current state.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PlanLimit": {
        "description": "A plan ceiling or a locked feature stopped an otherwise valid request.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "plan_limit_error",
                "code": "plan_limit_exceeded",
                "message": "You have reached the customer limit on the Free plan. Upgrade to add more.",
                "request_id": "req_5f2a91c0e8b74d3a9c1e"
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests. Back off and retry.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "A dependency is temporarily unavailable, or a required index is still building. Safe to retry.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/oauth/token": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Get an access token",
        "operationId": "createAccessToken",
        "security": [],
        "description": "Exchange a client id and secret for a bearer token that lasts one hour.\n\nCredentials may be sent three ways — pick whichever your HTTP client makes\neasiest. All three are equivalent:\n\n- a JSON body (shown below),\n- a form-encoded body, which is what most OAuth libraries send,\n- HTTP Basic, with the client id as the username. Basic wins if both are\n  present, so a body parameter cannot downgrade a header.\n\n**Cache the token.** One call an hour is the expected pattern; the token\nendpoint is rate limited to 20 requests per minute per IP, and ten consecutive\nfailures against one client id lock it out for fifteen minutes.\n\nEvery credential failure — unknown client id, wrong secret, revoked credential,\nexpired credential — answers the same `401 invalid_client`. Telling you which\none it was would tell an attacker which client ids exist.\n\nTwo things are checked before a token is issued: that the account's plan\nincludes API access, and that the calling IP passes the account's IP\nallow-list if one is set. A blocked address answers `403 ip_not_allowed`\nand gets no token at all.\n\nThe first time an account reaches this endpoint, the **API Explorer**\nachievement becomes collectable in the console. Nothing to do — it\nunlocks on its own.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "client_id",
                  "client_secret"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "client_credentials"
                    ],
                    "default": "client_credentials"
                  },
                  "client_id": {
                    "type": "string",
                    "example": "tlc_811fc5491673d78d047a1085da2e22b7"
                  },
                  "client_secret": {
                    "type": "string",
                    "example": "tls_9f3c…"
                  }
                }
              },
              "examples": {
                "json": {
                  "summary": "JSON body",
                  "value": {
                    "client_id": "tlc_811fc5491673d78d047a1085da2e22b7",
                    "client_secret": "tls_9f3c8a21b6d54e7f90a1c2b3d4e5f60718293a4b5c6d7e8f"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A one-hour bearer token.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessToken"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/oauth/introspect": {
      "get": {
        "tags": [
          "Authentication"
        ],
        "summary": "Inspect the current token",
        "operationId": "introspectToken",
        "description": "What this token can do: which account it belongs to and exactly which scopes it\nholds.\n\nCall it first when something is unexpected. Between the account id and the scope\nlist it explains almost every surprising `403`, and it costs nothing.",
        "responses": {
          "200": {
            "description": "The token is valid.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenIntrospection"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/conversations": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "summary": "List conversations",
        "operationId": "listConversations",
        "description": "Conversations in one status bucket, filtered and paginated.\n\n`status` defaults to `open`, which also folds in `missed` — a missed call is an\nopen conversation nobody has picked up, not a separate queue.\n\nFilters combine with AND; repeated values within one filter combine with OR, and\nmay be sent either repeated (`?label=vip&label=urgent`) or comma-separated\n(`?label=vip,urgent`). Two filters take sentinel values:\n`assignee_id=unassigned` finds the waiting line, and `team_id=none` finds\nconversations no team owns.\n\nFetching a large `status=resolved` set? Add `created_after` / `created_before`.\nOpen buckets stay small; the resolved archive does not.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Which bucket to read.",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "pending",
                "on_hold",
                "resolved"
              ],
              "default": "open"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "Field to order by.",
            "schema": {
              "type": "string",
              "enum": [
                "last_activity_at",
                "created_at",
                "priority",
                "flag"
              ],
              "default": "last_activity_at"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "One or more inbox ids.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inbox_type",
            "in": "query",
            "required": false,
            "description": "One or more channel types, e.g. `whatsapp`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assignee_id",
            "in": "query",
            "required": false,
            "description": "Agent ids, or `unassigned` for the waiting line.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "team_id",
            "in": "query",
            "required": false,
            "description": "Team ids, or `none` for conversations with no team.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "description": "low | medium | high | urgent.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "flag",
            "in": "query",
            "required": false,
            "description": "Flag emoji values.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "label",
            "in": "query",
            "required": false,
            "description": "Label names. A conversation matches if it carries any of them.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only this contact's conversations.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "customer_id",
            "in": "query",
            "required": false,
            "description": "Only this customer's conversations.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pinned",
            "in": "query",
            "required": false,
            "description": "Only pinned, or only unpinned.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "time_window",
            "in": "query",
            "required": false,
            "description": "Shorthand for a created-at range.",
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "yesterday",
                "last_7_days",
                "last_30_days"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          },
          {
            "name": "updated_after",
            "in": "query",
            "required": false,
            "description": "Only conversations touched at or after this moment — the cheap way to poll for changes.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conversations returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Conversations"
        ],
        "summary": "Create a conversation",
        "operationId": "createConversation",
        "description": "Open a conversation in an inbox.\n\n`inbox_id` is enough on its own — the channel type is read from the inbox, so\nyou never have to keep the two in sync. Get the ids from `GET /v1/inboxes`.\n\nIdentify the contact either by `contact_id`, or by a `contact` object carrying a\n`phone` or an `email`. The second form is what an integration usually wants: an\nunknown phone number creates the contact rather than failing.\n\nPass a `message` object to send the first message in the same call — the same\nbody `POST /v1/conversations/{id}/messages` takes, including\n`{\"type\": \"template\", …}` for WhatsApp. The created message comes back under\n`initial_message`.\n\n**Which inboxes can start a conversation?** Live chat, the API inbox, Instagram\nDM, Facebook Messenger and TikTok are inbound-only: the customer must write\nfirst, because there is no way to address them until they do.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "inbox_id"
                ],
                "properties": {
                  "inbox_id": {
                    "type": "string"
                  },
                  "contact_id": {
                    "type": "string",
                    "description": "An existing contact. Mutually exclusive with `contact`."
                  },
                  "contact": {
                    "type": "object",
                    "description": "Find-or-create by identifier.",
                    "properties": {
                      "phone": {
                        "type": "string",
                        "example": "+972501234567"
                      },
                      "email": {
                        "type": "string",
                        "format": "email"
                      },
                      "name": {
                        "type": "string"
                      }
                    }
                  },
                  "subject": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "urgent"
                    ],
                    "default": "medium"
                  },
                  "assignee_id": {
                    "type": "string"
                  },
                  "team_id": {
                    "type": "string"
                  },
                  "labels": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "string"
                    }
                  },
                  "tags": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "string"
                    }
                  },
                  "flag": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "message": {
                    "type": "object",
                    "description": "Optional first message. Same shape as the send-message body.",
                    "additionalProperties": true
                  }
                }
              },
              "examples": {
                "byPhone": {
                  "summary": "WhatsApp, new contact, with the first message",
                  "value": {
                    "inbox_id": "3",
                    "contact": {
                      "phone": "+972501234567",
                      "name": "Dana Levi"
                    },
                    "priority": "high",
                    "message": {
                      "type": "text",
                      "content": "Hi Dana — your order has shipped."
                    }
                  }
                },
                "existingContact": {
                  "summary": "Existing contact, no message yet",
                  "value": {
                    "inbox_id": "3",
                    "contact_id": "42",
                    "subject": "Refund request"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Conversation created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/conversations/counts": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "summary": "Queue counts",
        "operationId": "conversationCounts",
        "description": "The numbers behind the inbox sidebar badges, in one call.\n\n`assigned` counts open conversations with a human owner — the console shows a\nper-agent \"Mine\" badge, which has no meaning for a machine credential.",
        "responses": {
          "200": {
            "description": "Counts returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationCounts"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/conversations/{conversation_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConversationId"
        }
      ],
      "get": {
        "tags": [
          "Conversations"
        ],
        "summary": "Get a conversation",
        "operationId": "getConversation",
        "description": "Everything stored about one conversation, including its custom attributes.",
        "responses": {
          "200": {
            "description": "The conversation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Conversations"
        ],
        "summary": "Update a conversation",
        "operationId": "updateConversation",
        "description": "Change assignment, routing, priority, flag, labels, subject or status. Only the\nfields you send are touched.\n\n`status` accepts `open`, `pending` and `resolved`. Moving **to** `on_hold` is\nnot allowed here, because a hold carries a deadline — use\n`POST /v1/conversations/{id}/hold`. Moving **out** of on-hold by setting another\nstatus works and clears the deadline.\n\nTwo assignments have side effects worth knowing about:\n\n- Assigning a **team** whose auto-assign rule is on immediately hands the\n  conversation to a random online member.\n- Assigning an **AI agent** starts an AI session; the response carries an\n  `assignment` object with its `ai_session_id`. Assigning a human to a\n  conversation an AI is handling ends that session silently — the human takeover\n  the console does.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "pending",
                      "resolved"
                    ]
                  },
                  "assignee_id": {
                    "type": "string",
                    "description": "Empty string unassigns."
                  },
                  "team_id": {
                    "type": "string",
                    "description": "Empty string detaches the team."
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "urgent"
                    ]
                  },
                  "flag": {
                    "type": "string"
                  },
                  "labels": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "string"
                    }
                  },
                  "tags": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "string"
                    }
                  },
                  "subject": {
                    "type": "string"
                  },
                  "pinned": {
                    "type": "boolean"
                  }
                }
              },
              "examples": {
                "resolve": {
                  "summary": "Resolve",
                  "value": {
                    "status": "resolved"
                  }
                },
                "assign": {
                  "summary": "Assign to an agent and raise priority",
                  "value": {
                    "assignee_id": "agent_12",
                    "priority": "urgent"
                  }
                },
                "label": {
                  "summary": "Replace the labels",
                  "value": {
                    "labels": [
                      "vip",
                      "billing"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated conversation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Conversations"
        ],
        "summary": "Delete a conversation (email inboxes only)",
        "operationId": "deleteConversation",
        "description": "Permanently delete a conversation, its messages, notes and stored attachments.\n\n**Email inboxes only.** Every other channel keeps an immutable history on\npurpose: a WhatsApp or SMS thread is a record of what was actually sent to a\ncustomer. Email is deletable because an inbox routinely receives mail that\nshould never have been filed at all.\n\nA non-email conversation answers `403` with `code: delete_not_permitted`.\nThis cannot be undone.",
        "responses": {
          "200": {
            "description": "Conversation deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/conversations/{conversation_id}/hold": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConversationId"
        }
      ],
      "post": {
        "tags": [
          "Conversations"
        ],
        "summary": "Put a conversation on hold",
        "operationId": "holdConversation",
        "description": "Park a conversation until a deadline. It leaves the active queues and comes back\nby itself when the timer expires — or sooner, if the customer writes in.\n\nThe assignment is deliberately left alone: on hold means \"come back to me later\",\nso the conversation returns to the same agent.\n\n`until` is read in the **account's** timezone (Settings → General), never the\ncaller's, because a deadline is business logic rather than a display preference.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "preset": {
                    "type": "string",
                    "enum": [
                      "1_hour",
                      "4_hours",
                      "tomorrow_9am",
                      "1_week",
                      "custom"
                    ]
                  },
                  "until": {
                    "type": "string",
                    "description": "Required for `custom`. An ISO date or datetime in the account timezone.",
                    "example": "2026-09-01T14:30"
                  }
                }
              },
              "examples": {
                "preset": {
                  "summary": "Until tomorrow morning",
                  "value": {
                    "preset": "tomorrow_9am"
                  }
                },
                "custom": {
                  "summary": "A specific moment",
                  "value": {
                    "preset": "custom",
                    "until": "2026-09-01T14:30"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The conversation, now on hold.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "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": {
        "tags": [
          "Conversations"
        ],
        "summary": "Release a hold",
        "operationId": "releaseConversationHold",
        "description": "Release a hold early and return the conversation to its queue.",
        "responses": {
          "200": {
            "description": "The conversation, released.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/conversations/{conversation_id}/customer": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConversationId"
        }
      ],
      "put": {
        "tags": [
          "Conversations"
        ],
        "summary": "Move the conversation to a different customer",
        "operationId": "changeConversationCustomer",
        "description": "Re-parent this conversation's contact under a different customer.\n\nA contact cannot belong to two customers at once, so this moves **all** of that\ncontact's conversations, not just this one. The response reports how many, under\n`conversations_moved`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "customer_id"
                ],
                "properties": {
                  "customer_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The conversation, re-parented.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          },
          "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"
          }
        }
      }
    },
    "/conversations/{conversation_id}/custom-attributes": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConversationId"
        }
      ],
      "get": {
        "tags": [
          "Conversations"
        ],
        "summary": "Read a conversation's custom attributes",
        "operationId": "getConversationCustomAttributes",
        "description": "The attribute values stored on this conversation, with their definitions resolved.",
        "responses": {
          "200": {
            "description": "Values returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationCustomAttributes"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Conversations"
        ],
        "summary": "Set custom attribute values",
        "operationId": "updateConversationCustomAttributes",
        "description": "A partial merge: attributes you do not mention keep their value. Send `null` for\none to clear it.\n\nValues are validated against the account's schema (`GET /v1/conversation-attributes`),\nso an unknown attribute id, or a value outside a select list, is a `400` naming\nthe field rather than bad data stored quietly.\n\nWriting an attribute does **not** move the conversation up the queue — filing\ninformation is bookkeeping, not a customer interaction.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "values": {
                    "type": "object",
                    "additionalProperties": true
                  }
                },
                "description": "Either `{\"values\": {...}}` or the attribute map at the top level."
              },
              "examples": {
                "set": {
                  "summary": "Set two attributes",
                  "value": {
                    "values": {
                      "reason_for_contact": "billing",
                      "order_number": "SO-4192"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Values stored.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationCustomAttributes"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/inboxes": {
      "get": {
        "tags": [
          "Conversations"
        ],
        "summary": "List inboxes",
        "operationId": "listInboxes",
        "description": "Every inbox in the account, with the id you pass as `inbox_id`.\n\nProvider secrets — access tokens, webhook signing keys, mailbox passwords — are\nnever included. No endpoint on this API returns them.\n\n**Scope:** `conversations` or `messages`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Filter to one channel type.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "description": "Only enabled, or only disabled, inboxes.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Inboxes returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Inbox"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/inboxes/{inbox_id}/templates": {
      "parameters": [
        {
          "name": "inbox_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Messages"
        ],
        "summary": "List WhatsApp templates",
        "operationId": "listWhatsAppTemplates",
        "description": "Approved WhatsApp templates for one inbox, with how many body variables each\nexpects.\n\nCall it before sending a template: `name` and `body_variable_count` are what you\nneed to build the send. Only templates with `status: approved` can be sent.\n\nA non-WhatsApp inbox returns an empty list rather than an error, so a client can\ncall this uniformly.",
        "responses": {
          "200": {
            "description": "Templates returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WhatsAppTemplate"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/conversations/{conversation_id}/messages": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConversationId"
        }
      ],
      "get": {
        "tags": [
          "Messages"
        ],
        "summary": "List messages",
        "operationId": "listMessages",
        "description": "Messages in a conversation, oldest first by default.\n\nPrivate notes are included. Pass `include_private=false` to get only what the\ncustomer actually saw — usually what you want when syncing a transcript\nsomewhere else.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "Chronological direction.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "asc"
            }
          },
          {
            "name": "include_private",
            "in": "query",
            "required": false,
            "description": "Include internal notes.",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "Only inbound or only outbound.",
            "schema": {
              "type": "string",
              "enum": [
                "incoming",
                "outgoing"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "Messages returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Messages"
        ],
        "summary": "Send a message",
        "operationId": "sendMessage",
        "description": "Send a message, an internal note, or a WhatsApp template. `type` selects the\nshape of the request:\n\n| `type` | What it sends | Required |\n| --- | --- | --- |\n| `text` *(default)* | A plain text message | `content` |\n| `media` | A file by URL | `content` (an https URL), `content_type` |\n| `note` | An internal note, never delivered to the customer | `content` |\n| `template` | An approved WhatsApp template | `template.name` |\n\n### The WhatsApp 24-hour window\n\nWhatsApp only accepts free-form messages within 24 hours of the customer's last\nmessage. Outside it, this endpoint answers `409` with\n`code: whatsapp_window_closed` **before** contacting the provider, and the error\ncarries `details.last_customer_message_at` so you can show the operator why.\nSend a template instead — that is what templates are for.\n\n### Other channel rules\n\n- **TikTok** — 48-hour window plus a per-window message cap; text and image only.\n- **Voice** — private notes only.\n- **SMS** — costs credits per segment. Insufficient credits answers `402`.\n- **Templates** — cost credits by category (`utility`, `marketing`,\n  `authentication`). Pass the right one: it decides the price.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "text",
                      "media",
                      "note",
                      "template"
                    ],
                    "default": "text"
                  },
                  "content": {
                    "type": "string",
                    "description": "The text, or — for `media` — the https URL of the file."
                  },
                  "content_type": {
                    "type": "string",
                    "enum": [
                      "image",
                      "video",
                      "audio",
                      "document",
                      "sticker",
                      "location"
                    ],
                    "description": "Required for `media`."
                  },
                  "caption": {
                    "type": "string",
                    "maxLength": 3000
                  },
                  "reply_to_message_id": {
                    "type": "string",
                    "description": "Quote an earlier message. Supported on WhatsApp and TikTok."
                  },
                  "attachments": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "template": {
                    "type": "object",
                    "description": "Required for `type: template`.",
                    "required": [
                      "name"
                    ],
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "From GET /v1/inboxes/{inbox_id}/templates."
                      },
                      "category": {
                        "type": "string",
                        "enum": [
                          "utility",
                          "marketing",
                          "authentication"
                        ],
                        "default": "utility",
                        "description": "Decides what the send costs."
                      },
                      "body_variables": {
                        "type": "array",
                        "maxItems": 10,
                        "items": {
                          "type": "string"
                        },
                        "description": "Values for the template's placeholders, in order."
                      },
                      "header": {
                        "type": "object",
                        "description": "Media header, when the template has one.",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "image",
                              "video",
                              "document"
                            ]
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          },
                          "filename": {
                            "type": "string",
                            "description": "Display name for a document header."
                          }
                        }
                      },
                      "button_url_variable": {
                        "type": "string"
                      },
                      "button_url_variable_2": {
                        "type": "string"
                      },
                      "coupon_code": {
                        "type": "string"
                      },
                      "otp": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "examples": {
                "text": {
                  "summary": "Plain text",
                  "value": {
                    "type": "text",
                    "content": "Your order is on its way."
                  }
                },
                "note": {
                  "summary": "Internal note",
                  "value": {
                    "type": "note",
                    "content": "Customer called about this earlier — see ticket 4192."
                  }
                },
                "media": {
                  "summary": "Send a PDF",
                  "value": {
                    "type": "media",
                    "content_type": "document",
                    "content": "https://files.example.com/invoice-4192.pdf",
                    "caption": "Your invoice"
                  }
                },
                "template": {
                  "summary": "WhatsApp template with variables",
                  "value": {
                    "type": "template",
                    "template": {
                      "name": "order_shipped",
                      "category": "utility",
                      "body_variables": [
                        "Dana",
                        "SO-4192",
                        "Tuesday"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message created and queued for delivery.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/conversations/{conversation_id}/messages/{message_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ConversationId"
        },
        {
          "name": "message_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Messages"
        ],
        "summary": "Get a message",
        "operationId": "getMessage",
        "responses": {
          "200": {
            "description": "The message.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Messages"
        ],
        "summary": "Delete a message",
        "operationId": "deleteMessage",
        "description": "Remove one message from a conversation.\n\nThere is no equivalent in the console — this is API-only, and it is genuinely\ndestructive. It deletes **our** record of the message, not the copy the customer\nalready received on WhatsApp, SMS or email. Use it to redact something that\nshould never have been stored, not to \"unsend\".\n\nThe conversation's message count is corrected and attachments are detached from\nthe Files Warehouse index. Every delete is written to the audit log with the\ncredential that made it.",
        "responses": {
          "200": {
            "description": "Message deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/customers": {
      "get": {
        "tags": [
          "Customers"
        ],
        "summary": "List customers",
        "operationId": "listCustomers",
        "description": "Customers in the account, filtered and paginated.\n\n`search` is a case-insensitive substring match over name, phone, email, industry\nand address. When you have an exact identifier, `GET /v1/customers/search` is\nthe better call.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match across the customer's text fields.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lifecycle_stage",
            "in": "query",
            "required": false,
            "description": "One or more stages, e.g. `lead`. Unknown stages are a 400 listing what this account uses.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "One or more tags. Matches if the customer carries any of them.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assigned_agent",
            "in": "query",
            "required": false,
            "description": "Exact match on the assigned agent field.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "Field to order by.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "updated_at",
                "name"
              ],
              "default": "created_at"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customers returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Customer"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Customers"
        ],
        "summary": "Create a customer",
        "operationId": "createCustomer",
        "description": "Create a customer.\n\nCounts against the plan's customer limit — a full account answers `402` with\n`code: plan_limit_exceeded` rather than silently discarding the record.\n\nCreating a customer fires the Studio *customer changed* trigger and writes a\njourney event, exactly as the console does, so automations react to API-created\nrecords the same way.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 300
                  },
                  "phone": {
                    "type": "string",
                    "description": "International format, e.g. +972501234567."
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "industry": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "website": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "address": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "assigned_agent": {
                    "type": "string"
                  },
                  "lifecycle_stage": {
                    "type": "string",
                    "default": "lead"
                  },
                  "tags": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "examples": {
                "basic": {
                  "summary": "A new lead",
                  "value": {
                    "name": "Acme Ltd.",
                    "email": "hello@acme.example",
                    "phone": "+972501234567",
                    "lifecycle_stage": "lead",
                    "tags": [
                      "inbound"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/customers/search": {
      "get": {
        "tags": [
          "Customers"
        ],
        "summary": "Search customers",
        "operationId": "searchCustomers",
        "description": "Find customers by an exact identifier, or by free text.\n\nPrefer `phone` or `email`: those are exact, index-backed matches and the natural\nway to answer \"do I already have this company?\" before creating a duplicate.\n`q` falls back to the same substring search the list endpoint uses.\n\nAt least one of the three is required.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "phone",
            "in": "query",
            "required": false,
            "description": "Exact phone match.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "description": "Exact email match, case-insensitive.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text substring search.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matches returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Customer"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/customers/{customer_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CustomerId"
        }
      ],
      "get": {
        "tags": [
          "Customers"
        ],
        "summary": "Get a customer",
        "operationId": "getCustomer",
        "description": "One customer. Pass `include=contacts` to get its channel identities in the same call.",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Set to `contacts` to embed the linked contacts.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The customer.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Customers"
        ],
        "summary": "Update a customer",
        "operationId": "updateCustomer",
        "description": "Only the fields you send change. Changing `lifecycle_stage` writes a journey event.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "industry": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "assigned_agent": {
                    "type": "string"
                  },
                  "lifecycle_stage": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "examples": {
                "promote": {
                  "summary": "Move to customer stage",
                  "value": {
                    "lifecycle_stage": "customer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated customer.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Customer"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Customers"
        ],
        "summary": "Delete a customer",
        "operationId": "deleteCustomer",
        "description": "Delete a customer.\n\nContacts and conversations are **unlinked**, not deleted: the message history is\na record of what was said to a real person and survives the customer record it\nhappened to be filed under. Object records stored under the customer (deals,\nservice calls…) go with it.\n\nThe response reports how many contacts and conversations were unlinked.",
        "responses": {
          "200": {
            "description": "Customer deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/DeletedResource"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "unlinked_contacts": {
                          "type": "integer"
                        },
                        "unlinked_conversations": {
                          "type": "integer"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/customers/{customer_id}/contacts": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CustomerId"
        }
      ],
      "get": {
        "tags": [
          "Customers"
        ],
        "summary": "List a customer's contacts",
        "operationId": "listCustomerContacts",
        "description": "The channel identities linked to this customer — what you pass as `contact_id` when starting a conversation.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "Contacts returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contact"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/objects": {
      "get": {
        "tags": [
          "Customer objects"
        ],
        "summary": "List object types",
        "operationId": "listCustomerObjects",
        "description": "Every object type in the account, with its field definitions.\n\n**Start here.** Each object's `id` is what you pass as `object_id` everywhere\nelse, and `fields[].key` is what goes in a record's `data`. The account's own\ncustom objects appear alongside the seeded ones (Contacts, Deals, Service Calls,\nTasks, Notes).",
        "parameters": [
          {
            "name": "include_disabled",
            "in": "query",
            "required": false,
            "description": "Also return object types that are switched off.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Object types returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerObject"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/objects/{object_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ObjectId"
        }
      ],
      "get": {
        "tags": [
          "Customer objects"
        ],
        "summary": "Get an object type",
        "operationId": "getCustomerObject",
        "description": "One object type and its full field schema.",
        "responses": {
          "200": {
            "description": "The object type.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerObject"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/objects/{object_id}/records": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ObjectId"
        }
      ],
      "get": {
        "tags": [
          "Customer objects"
        ],
        "summary": "List records across all customers",
        "operationId": "listObjectRecords",
        "description": "Every record of one object type, across every customer. This is how you ask\n\"all deals that closed this month\" without walking the customer list.\n\nFilter on a field's value with `field.<key>=<value>`, for example\n`?field.stage=Won&field.owner=agent_12`. Comparison is case-insensitive string\nequality, so select lists and free-text fields behave the same way; use\n`created_after` / `created_before` for date ranges.\n\nThis query is served by a Firestore collection-group index. If that index is\nstill building, the endpoint answers `503` with `code: index_required` rather\nthan returning a partial list — fall back to the per-customer endpoint in the\nmeantime.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          },
          {
            "name": "customer_id",
            "in": "query",
            "required": false,
            "description": "Narrow to one customer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "field.stage",
            "in": "query",
            "required": false,
            "description": "Match a field value exactly: `field.<key>=<value>`. Repeat for several fields.",
            "schema": {
              "type": "string"
            },
            "example": "Won"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          }
        ],
        "responses": {
          "200": {
            "description": "Records returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerObjectRecord"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/customers/{customer_id}/objects/{object_id}/records": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CustomerId"
        },
        {
          "$ref": "#/components/parameters/ObjectId"
        }
      ],
      "get": {
        "tags": [
          "Customer objects"
        ],
        "summary": "List one customer's records",
        "operationId": "listCustomerObjectRecords",
        "description": "Records of one object type belonging to one customer.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          }
        ],
        "responses": {
          "200": {
            "description": "Records returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CustomerObjectRecord"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Customer objects"
        ],
        "summary": "Create a record",
        "operationId": "createCustomerObjectRecord",
        "description": "Create a record under a customer.\n\nField values go in `data`, keyed by the `fields[].key` values from\n`GET /v1/objects/{object_id}`. They are validated against the object's schema:\na missing required field, or a select value outside the list, is a `400` naming\nthe field — with the per-field detail under `error.details.errors` — rather than\na record with bad data in it.\n\nCreating a record writes a journey event on the customer and fires the Studio\n*customer record changed* trigger.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Field values keyed by field key."
                  }
                }
              },
              "examples": {
                "deal": {
                  "summary": "A new deal",
                  "value": {
                    "data": {
                      "title": "Annual renewal",
                      "amount": 12000,
                      "stage": "Negotiation"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Record created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerObjectRecord"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/customers/{customer_id}/objects/{object_id}/records/{record_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CustomerId"
        },
        {
          "$ref": "#/components/parameters/ObjectId"
        },
        {
          "name": "record_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Customer objects"
        ],
        "summary": "Get a record",
        "operationId": "getCustomerObjectRecord",
        "responses": {
          "200": {
            "description": "The record.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerObjectRecord"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Customer objects"
        ],
        "summary": "Update a record",
        "operationId": "updateCustomerObjectRecord",
        "description": "Only the fields present in `data` change. Status transitions write journey events — a deal moving to `Won` or `Lost`, a service call being resolved.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "examples": {
                "win": {
                  "summary": "Close a deal",
                  "value": {
                    "data": {
                      "stage": "Won"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated record.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerObjectRecord"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Customer objects"
        ],
        "summary": "Delete a record",
        "operationId": "deleteCustomerObjectRecord",
        "description": "Deletes the record and removes any cross-object links pointing at it.",
        "responses": {
          "200": {
            "description": "Record deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/analytics/dashboards": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "List dashboards",
        "operationId": "listDashboards",
        "description": "Every dashboard in the account.\n\n`is_default: true` marks the dashboard Teloring seeds for a new account. It is\nan ordinary dashboard — it can be renamed and rearranged — the flag exists so an\nintegration can find \"the main one\" without matching on a name that might be in\nHebrew.",
        "responses": {
          "200": {
            "description": "Dashboards returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Dashboard"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/analytics/dashboards/{dashboard_id}": {
      "parameters": [
        {
          "name": "dashboard_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get a dashboard",
        "operationId": "getDashboard",
        "description": "A dashboard with its graphs, and optionally their current values.\n\nWithout `include=values` this is a cheap metadata read. With it, every graph is\nexecuted and gains a `value` object holding the same series and totals the\nconsole renders — up to 30 graphs per call, with `values_truncated_after` in the\nresponse if the dashboard has more.\n\nRunning the graphs is genuinely expensive. Cache the result rather than polling\nit, and prefer a schedule measured in minutes over one measured in seconds.\n\nOne caveat: a graph filtered to \"my conversations\" resolves `$AGENT_ID` against\nthe caller, and a machine credential is nobody in particular — such a graph\nlegitimately comes back empty here.",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Set to `values` to compute every graph.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The dashboard.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Dashboard"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/analytics/dashboards/{dashboard_id}/graphs": {
      "parameters": [
        {
          "name": "dashboard_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "List a dashboard's graphs",
        "operationId": "listDashboardGraphs",
        "description": "The graphs on one dashboard. `?include=values` computes each one.",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Set to `values` to compute every graph.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Graphs returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Graph"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/studio/flows": {
      "get": {
        "tags": [
          "Studio"
        ],
        "summary": "List flows",
        "operationId": "listStudioFlows",
        "description": "Every flow in the account, most recently edited first.\n\n`live` flows are running against incoming conversations right now; `draft` have\nnever been published, and `paused` were stopped deliberately.\n`has_unpublished_changes` tells you a live flow has edits that are not yet in\neffect.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by state.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "live",
                "paused",
                "disabled"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match on the flow name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Flows returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/StudioFlow"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/studio/flows/{flow_id}": {
      "parameters": [
        {
          "name": "flow_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Studio"
        ],
        "summary": "Get a flow with its blocks",
        "operationId": "getStudioFlow",
        "description": "One flow, with every block and trigger it contains and the settings inside each.\n\n`blocks[].settings` is block-specific by design — a *send WhatsApp template*\nblock and a *branch on business hours* block have nothing in common. Use\n`GET /v1/studio/blocks` as the dictionary.\n\n`connections` describes the wiring: which block's output leads to which block's\ninput, and through which handle. On a branching block the handle is what tells\nyou *which* branch, so do not ignore it.",
        "responses": {
          "200": {
            "description": "The flow.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioFlow"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/studio/blocks": {
      "get": {
        "tags": [
          "Studio"
        ],
        "summary": "List block and trigger types",
        "operationId": "listStudioBlockTypes",
        "description": "The catalog of every block and trigger Studio offers, with each one's settings\nschema.\n\nThis describes the platform rather than the account, so it is identical for\neverybody — fetch it once and cache it.",
        "responses": {
          "200": {
            "description": "Block types returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/StudioBlock"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/ai-world": {
      "get": {
        "tags": [
          "AI World"
        ],
        "summary": "List AI capabilities",
        "operationId": "listAiFeatures",
        "description": "Every AI capability and whether it is switched on for this account.",
        "responses": {
          "200": {
            "description": "Capabilities returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AiFeature"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/ai-world/{feature_key}": {
      "parameters": [
        {
          "name": "feature_key",
          "in": "path",
          "required": true,
          "description": "From `GET /v1/ai-world`, e.g. `ai_copilot`.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "AI World"
        ],
        "summary": "Get one capability",
        "operationId": "getAiFeature",
        "responses": {
          "200": {
            "description": "The capability.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiFeature"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "tags": [
          "AI World"
        ],
        "summary": "Switch a capability on or off",
        "operationId": "setAiFeature",
        "description": "Turn one AI capability on or off.\n\nMost of these consume AI credits every time they run — check\n`GET /v1/billing/usage-pricing` before enabling one across a busy account.\n\nThe response carries `changed`, which is `false` when the capability was already\nin the requested state. Note that switching a feature on does nothing if the\naccount's plan does not include AI World at all: the plan gate is checked where\nthe feature runs, so `GET /v1/billing/plan` is where that shows up.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enabled"
                ],
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  }
                }
              },
              "examples": {
                "on": {
                  "summary": "Enable",
                  "value": {
                    "enabled": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The capability, after the change.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiFeature"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/knowledge-bases": {
      "get": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "List knowledge bases",
        "operationId": "listKnowledgeBases",
        "description": "Every knowledge base in the account.\n\nRequires the Knowledge Base AI capability to be switched on. When it is off the\nendpoint answers `403` with `code: feature_disabled` — deliberately, so a client\ncan tell \"switched off\" from \"nothing indexed yet\".",
        "responses": {
          "200": {
            "description": "Knowledge bases returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KnowledgeBase"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "Create a knowledge base",
        "operationId": "createKnowledgeBase",
        "description": "Create an empty knowledge base. Counts against the plan's knowledge-base limit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              },
              "examples": {
                "basic": {
                  "summary": "Product manuals",
                  "value": {
                    "name": "Product manuals",
                    "description": "Everything the support AI may quote."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Knowledge base created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeBase"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/knowledge-bases/{kb_id}": {
      "parameters": [
        {
          "name": "kb_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "Get a knowledge base",
        "operationId": "getKnowledgeBase",
        "description": "One knowledge base with its indexing statistics.",
        "responses": {
          "200": {
            "description": "The knowledge base.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeBase"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "Delete a knowledge base",
        "operationId": "deleteKnowledgeBase",
        "description": "Delete a knowledge base and every source and chunk inside it. Irreversible.\n\nAny AI agent configured to answer from it keeps its configuration but stops\nretrieving anything — check `knowledge_base_ids` on your AI agents first.",
        "responses": {
          "200": {
            "description": "Knowledge base deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/knowledge-bases/{kb_id}/sources": {
      "parameters": [
        {
          "name": "kb_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "List sources",
        "operationId": "listKnowledgeBaseSources",
        "description": "The sources in a knowledge base, with their ingestion status.\n\n`processing` means the worker is still chunking and embedding; `ready` means it\ncan be retrieved from; `failed` means ingestion could not complete. Poll this\nafter adding a source.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by ingestion state.",
            "schema": {
              "type": "string",
              "enum": [
                "processing",
                "ready",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sources returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KnowledgeBaseSource"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "Add a source",
        "operationId": "addKnowledgeBaseSource",
        "description": "Add a source — a URL, or an uploaded file.\n\n**URL:** `application/json` with `{\"url\": \"https://…\"}`. Set `crawl_inner: true`\nto follow links within the same site. URLs are validated against private\naddress ranges before the worker fetches them.\n\n**File:** `multipart/form-data` with a `file` part. PDFs, Office documents,\nplain text and images are supported.\n\nReturns `202` immediately with the source in `processing`. Poll\n`GET /v1/knowledge-bases/{kb_id}/sources` for the outcome — a large PDF takes\nminutes, not seconds.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "crawl_inner": {
                    "type": "boolean",
                    "default": false,
                    "description": "Follow links within the same site."
                  }
                }
              },
              "examples": {
                "url": {
                  "summary": "Crawl a help centre",
                  "value": {
                    "url": "https://help.example.com/",
                    "crawl_inner": true
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. Ingestion runs in the background.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "knowledge_base_ingestion"
                      ]
                    },
                    "knowledge_base_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ]
                    },
                    "source": {
                      "type": "string",
                      "description": "The URL or filename that was submitted."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/BadRequest"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/knowledge-bases/{kb_id}/sources/{source_id}": {
      "parameters": [
        {
          "name": "kb_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "source_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "Delete a source",
        "operationId": "deleteKnowledgeBaseSource",
        "description": "Deletes one source and every chunk derived from it.",
        "responses": {
          "200": {
            "description": "Source deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/knowledge-bases/{kb_id}/chunks": {
      "parameters": [
        {
          "name": "kb_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Knowledge base"
        ],
        "summary": "List indexed chunks",
        "operationId": "listKnowledgeBaseChunks",
        "description": "The indexed passages in a knowledge base — literally what the AI can see.\n\nThis is the endpoint that lets you audit a knowledge base: if the assistant is\nanswering oddly, the answer is usually visible here. Filter to one source with\n`source_id`, or pass `include_content=false` for metadata only, which is much\ncheaper when walking a large base.\n\nEmbedding vectors are never returned: a thousand floats per chunk, meaningless\noutside the model that produced them, and they would dwarf every other field.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "source_id",
            "in": "query",
            "required": false,
            "description": "Only chunks from this source.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_content",
            "in": "query",
            "required": false,
            "description": "Return the passage text.",
            "schema": {
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Chunks returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KnowledgeBaseChunk"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/quick-replies": {
      "get": {
        "tags": [
          "Quick replies"
        ],
        "summary": "List quick replies",
        "operationId": "listQuickReplies",
        "description": "Quick replies in the account.\n\nBy default this returns the shared (`account`) replies **plus** every agent's\npersonal ones — the full library, which is what a credential managing it wants.\nNarrow with `scope`, or with `agent_id` for one agent's personal replies.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "account | personal.",
            "schema": {
              "type": "string",
              "enum": [
                "account",
                "personal"
              ]
            }
          },
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "description": "One agent's personal replies.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category_id",
            "in": "query",
            "required": false,
            "description": "Only replies in this category.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match on title and body.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Quick replies returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/QuickReply"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Quick replies"
        ],
        "summary": "Create a quick reply",
        "operationId": "createQuickReply",
        "description": "Create a quick reply.\n\n`scope` defaults to `account` — a shared snippet is almost always what an\nintegration means. For a personal one, pass `scope: \"personal\"` **and** the\n`agent_id` it belongs to; without an owner a personal reply would be invisible\nto everybody.\n\nBodies may contain merge variables such as `{{contact.name}}`. They are stored\nverbatim and resolved when an agent inserts the reply.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "body"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "account",
                      "personal"
                    ],
                    "default": "account"
                  },
                  "agent_id": {
                    "type": "string",
                    "description": "Required when scope is `personal`."
                  },
                  "category_id": {
                    "type": "string"
                  },
                  "category_name": {
                    "type": "string"
                  }
                }
              },
              "examples": {
                "shared": {
                  "summary": "A shared snippet",
                  "value": {
                    "title": "Refund policy",
                    "body": "Hi {{contact.name}}, our refund window is 14 days from delivery.",
                    "scope": "account"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Quick reply created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuickReply"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/quick-replies/categories": {
      "get": {
        "tags": [
          "Quick replies"
        ],
        "summary": "List categories",
        "operationId": "listQuickReplyCategories",
        "description": "The categories quick replies can be filed under.",
        "responses": {
          "200": {
            "description": "Categories returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/QuickReply"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/quick-replies/{quick_reply_id}": {
      "parameters": [
        {
          "name": "quick_reply_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Quick replies"
        ],
        "summary": "Get a quick reply",
        "operationId": "getQuickReply",
        "responses": {
          "200": {
            "description": "The quick reply.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuickReply"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Quick replies"
        ],
        "summary": "Update a quick reply",
        "operationId": "updateQuickReply",
        "description": "Only the fields you send change.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "body": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "account",
                      "personal"
                    ]
                  },
                  "category_id": {
                    "type": "string"
                  },
                  "category_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated quick reply.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuickReply"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Quick replies"
        ],
        "summary": "Delete a quick reply",
        "operationId": "deleteQuickReply",
        "responses": {
          "200": {
            "description": "Quick reply deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/forms": {
      "get": {
        "tags": [
          "Forms"
        ],
        "summary": "List forms",
        "operationId": "listForms",
        "description": "Every form in the account, with its submission count and public URL.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by publication state.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Filter by form type.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match on the form name.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Forms returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Form"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/forms/{form_id}": {
      "parameters": [
        {
          "name": "form_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Forms"
        ],
        "summary": "Get a form",
        "operationId": "getForm",
        "description": "One form, including its field definitions.\n\n`fields[].id` is the key each answer is stored under in a submission — fetch this\nonce and cache it if you are mapping submissions into another system.",
        "responses": {
          "200": {
            "description": "The form.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Form"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Forms"
        ],
        "summary": "Delete a form",
        "operationId": "deleteForm",
        "description": "Delete a form. Its public link stops working immediately.\n\nSubmissions already received are **kept** — they are records of what somebody\nactually told the business, and deleting the form they arrived through does not\nmake them untrue. Pull them with `GET /v1/form-submissions?form_id=…` first if\nyou need them elsewhere.",
        "responses": {
          "200": {
            "description": "Form deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/forms/{form_id}/submissions": {
      "parameters": [
        {
          "name": "form_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Forms"
        ],
        "summary": "List a form's submissions",
        "operationId": "listFormSubmissions",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Free-text search over the submitted values.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Submissions returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FormSubmission"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/form-submissions": {
      "get": {
        "tags": [
          "Forms"
        ],
        "summary": "List submissions",
        "operationId": "listAllFormSubmissions",
        "description": "Submissions across every form, newest first.\n\nEach submission carries the answers twice: `answers` is the flat\n`{field_id: value}` map most integrations want, and `answers_detail` keeps each\nanswer's label and type so you can render a submission without also fetching the\nform.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "form_id",
            "in": "query",
            "required": false,
            "description": "Only this form's submissions.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only submissions linked to this contact.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Free-text search over the submitted values.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Submissions returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FormSubmission"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/form-submissions/{submission_id}": {
      "parameters": [
        {
          "name": "submission_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Forms"
        ],
        "summary": "Get a submission",
        "operationId": "getFormSubmission",
        "responses": {
          "200": {
            "description": "The submission.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FormSubmission"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/signature/documents": {
      "get": {
        "tags": [
          "Document signature"
        ],
        "summary": "List documents",
        "operationId": "listSignatureDocuments",
        "description": "Every document in the signature library.\n\n`status=active` are the ones with signature fields placed, and therefore the only\nones a signing link can be created for. `status=draft` still need a pass through\nthe console's editor.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "draft | active.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Documents returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SignatureDocument"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Document signature"
        ],
        "summary": "Upload a PDF",
        "operationId": "uploadSignatureDocument",
        "description": "Upload a PDF into the signature library. `multipart/form-data` with a `file`\npart.\n\nThe document arrives as a **draft**. It cannot be sent for signature until\nsomebody places the signature fields in the console's editor — a signature field\nis a coordinate on a page, and a JSON body of pixel offsets is not a contract\nanybody should have to write. That is why this returns `status: \"draft\"` rather\nthan something immediately usable.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The PDF."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document uploaded, awaiting field placement.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureDocument"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/signature/links": {
      "get": {
        "tags": [
          "Document signature"
        ],
        "summary": "List signing links",
        "operationId": "listSigningLinks",
        "description": "Signing links. `status=pending` is the waiting-to-sign list.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "pending | signed | declined | expired.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "document_id",
            "in": "query",
            "required": false,
            "description": "Only links for this document.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Signing links returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SigningLink"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Document signature"
        ],
        "summary": "Create a signing link",
        "operationId": "createSigningLink",
        "description": "Create a signing link for an **active** document. **Costs credits.**\n\nBoth `customer_id` and `contact_id` are required. The customer is the business\nthe document belongs to; the contact is the person who will sign it — and a\nsigned document that cannot say who signed it is not worth much.\n\n**Safe to retry.** Calling this twice for the same document and contact returns\nthe existing link instead of creating a second one, and does not charge again.\n`created` in the response tells you which happened, and the status code follows\nit (`201` for a new link, `200` for an existing one).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "document_id",
                  "customer_id",
                  "contact_id"
                ],
                "properties": {
                  "document_id": {
                    "type": "string"
                  },
                  "customer_id": {
                    "type": "string"
                  },
                  "contact_id": {
                    "type": "string"
                  },
                  "client_id": {
                    "type": "string",
                    "description": "Your own reference for this signer, echoed back on the link."
                  },
                  "inbox_id": {
                    "type": "string"
                  },
                  "conversation_id": {
                    "type": "string"
                  },
                  "custom_attributes": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Values pre-filled into the document's fields."
                  }
                }
              },
              "examples": {
                "basic": {
                  "summary": "Send a contract",
                  "value": {
                    "document_id": "doc_9f1",
                    "customer_id": "44",
                    "contact_id": "42"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "An existing pending link was returned. Nothing was charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningLink"
                }
              }
            }
          },
          "201": {
            "description": "Signing link created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningLink"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/signature/links/{link_id}": {
      "parameters": [
        {
          "name": "link_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "tags": [
          "Document signature"
        ],
        "summary": "Revoke a signing link",
        "operationId": "deleteSigningLink",
        "description": "Revoke a pending signing link.\n\nOnly `pending` links can be revoked. Once somebody has signed, the link is part\nof the audit trail of a completed document and cannot be removed — that answers\n`400` with `code: link_not_pending`.",
        "responses": {
          "200": {
            "description": "Signing link revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/signature/signed-documents": {
      "get": {
        "tags": [
          "Document signature"
        ],
        "summary": "List signed documents",
        "operationId": "listSignedDocuments",
        "description": "Completed and declined signings, newest first. A declined signing carries the reason the signer gave.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "completed | declined.",
            "schema": {
              "type": "string",
              "enum": [
                "completed",
                "declined"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Signed documents returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SignedDocument"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/account": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Get account details",
        "operationId": "getAccount",
        "description": "Everything on Settings → General, plus the read-only facts: the account id, the\nplan it is on, when it was created and who owns it.\n\nWorth calling once at the start of an integration. `plan` decides whether the\nrest of this API will work at all — `GET /v1/billing/plan` has the detail.\n\n**Scope:** `account`",
        "responses": {
          "200": {
            "description": "The account.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "patch": {
        "tags": [
          "Account"
        ],
        "summary": "Update account details",
        "operationId": "updateAccount",
        "description": "Update the account's general and invoicing details.\n\n**`billing_country` is guarded.** An Israeli account cannot be moved: the country\nalready determined the VAT on invoices that have been issued. Attempting it\nanswers `400` with `code: country_locked`. `billing_country_locked` on the GET\ntells you in advance.\n\nInvoice fields — `business_tax_id`, `business_address`, `business_city`,\n`business_contact_name` — are audited separately from the rest, because they are\nprinted on legal documents.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "business_name": {
                    "type": "string",
                    "maxLength": 160
                  },
                  "industry": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "contact_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "contact_phone": {
                    "type": "string",
                    "maxLength": 32
                  },
                  "default_language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "he"
                    ]
                  },
                  "timezone": {
                    "type": "string",
                    "example": "Asia/Jerusalem"
                  },
                  "default_currency": {
                    "type": "string",
                    "example": "ILS"
                  },
                  "business_tax_id": {
                    "type": "string",
                    "maxLength": 32
                  },
                  "business_address": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "business_city": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "business_contact_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "billing_country": {
                    "type": "string",
                    "description": "ISO 3166-1 alpha-2. Locked for Israeli accounts once billing starts."
                  }
                }
              },
              "examples": {
                "details": {
                  "summary": "Update invoicing details",
                  "value": {
                    "business_tax_id": "514123456",
                    "business_address": "12 Rothschild Blvd",
                    "business_city": "Tel Aviv"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated account.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/business-hours": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "List business-hours schedules",
        "operationId": "listBusinessHours",
        "description": "Every named schedule, with the holidays that will next close it.\n\nSchedules are what Studio branches on and what reports use to separate \"slow\nreply\" from \"out of hours\".\n\n**Scope:** `business_hours`",
        "responses": {
          "200": {
            "description": "Schedules returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BusinessHours"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Account"
        ],
        "summary": "Create a schedule",
        "operationId": "createBusinessHours",
        "description": "Create a named schedule.\n\n`days` maps weekday names to opening periods. A day with no periods is closed.\nTimes are read in the schedule's own `timezone`, falling back to the account's.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "timezone": {
                    "type": "string",
                    "example": "Asia/Jerusalem"
                  },
                  "days": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "holiday_calendar_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "consider_holidays": {
                    "type": "boolean"
                  },
                  "exceptions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              },
              "examples": {
                "weekdays": {
                  "summary": "Sunday to Thursday, 09:00–17:00",
                  "value": {
                    "name": "Support hours",
                    "timezone": "Asia/Jerusalem",
                    "days": {
                      "sunday": [
                        {
                          "start": "09:00",
                          "end": "17:00"
                        }
                      ],
                      "monday": [
                        {
                          "start": "09:00",
                          "end": "17:00"
                        }
                      ],
                      "tuesday": [
                        {
                          "start": "09:00",
                          "end": "17:00"
                        }
                      ],
                      "wednesday": [
                        {
                          "start": "09:00",
                          "end": "17:00"
                        }
                      ],
                      "thursday": [
                        {
                          "start": "09:00",
                          "end": "17:00"
                        }
                      ],
                      "friday": [],
                      "saturday": []
                    },
                    "consider_holidays": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Schedule created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessHours"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/business-hours/{schedule_id}": {
      "parameters": [
        {
          "name": "schedule_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "patch": {
        "tags": [
          "Account"
        ],
        "summary": "Update a schedule",
        "operationId": "updateBusinessHours",
        "description": "System schedules cannot be edited — those answer `403` with `code: system_schedule`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated schedule.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessHours"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Account"
        ],
        "summary": "Delete a schedule",
        "operationId": "deleteBusinessHours",
        "description": "Delete a schedule. System schedules cannot be deleted.\n\nStudio flows branching on this schedule keep their configuration but stop\nresolving it, so check your flows before deleting one that is in use.",
        "responses": {
          "200": {
            "description": "Schedule deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/holidays": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "List holiday calendars",
        "operationId": "listHolidays",
        "description": "Holiday calendars available to schedules, with their dates for a year.\n\nBoth kinds are returned: the calendars Teloring maintains (Jewish Israeli\nholidays, Christian holidays) and any the account added itself.\n\n**Scope:** `business_hours`",
        "parameters": [
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Four-digit year. Defaults to the current one.",
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Calendars returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/HolidayCalendar"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/conversation-attributes": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Get the conversation-attribute schema",
        "operationId": "listConversationAttributes",
        "description": "The account's conversation-attribute schema: the custom fields a conversation can\ncarry.\n\n`api_id` is the key you use when writing values at\n`PATCH /v1/conversations/{id}/custom-attributes`, and `type` decides what a value\nmay be — the write endpoint enforces it.\n\nRead-only on purpose. This is a *schema*, and reshaping it from a machine\ncredential would silently invalidate values on conversations that already carry\nthem.\n\n**Scope:** `conversation_attributes`",
        "responses": {
          "200": {
            "description": "The schema.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationAttributeSchema"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/agents": {
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "List agents",
        "operationId": "listAgents",
        "description": "Every agent in the account, human and AI, with their role. The `id` here is what goes in `assignee_id` on a conversation and in the SSO agent allowlist.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "human | ai.",
            "schema": {
              "type": "string",
              "enum": [
                "human",
                "ai"
              ]
            }
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "description": "Only active, or only deactivated, agents.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match on name and email.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agents returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Agent"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Create a human agent",
        "operationId": "createAgent",
        "description": "Create a human agent.\n\n⚠️ **This may charge the card on file.** An agent occupies a seat; if the plan\nhas none free, a prorated charge is taken for the rest of the billing period,\nexactly as in the console. Two consequences to design around:\n\n- A `402` with `code: seat_charge_failed` means the card was declined and\n  **nothing was created** — the agent is rolled back before the response is\n  written, so a retry is safe.\n- A `201` may carry a `seat_charge` object saying what was charged. Log it:\n  \"why did my invoice go up\" is a question an automated provisioning integration\n  will eventually have to answer.\n\nOmit `password` and the new agent is emailed a one-time link to set their own —\nthe right choice for a real person. Supply one and the account works\nimmediately, which suits a service account a machine will drive.\n\n`role_id` comes from `GET /v1/roles`. Omitted, the account's default Agent role\nis applied, which is a working least-privilege role rather than no permissions.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "name"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Must be unique across all of Teloring."
                  },
                  "name": {
                    "type": "string"
                  },
                  "role_id": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "description": "Omit to email a set-password link instead."
                  },
                  "phone": {
                    "type": "string"
                  },
                  "department": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "he"
                    ]
                  }
                }
              },
              "examples": {
                "invite": {
                  "summary": "Invite a new agent",
                  "value": {
                    "email": "dana@example.com",
                    "name": "Dana Levi",
                    "role_id": "TegbEuzpFS4MvIlTOxBz",
                    "department": "Support"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Agent created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/agents/{agent_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Get an agent",
        "operationId": "getAgent",
        "responses": {
          "200": {
            "description": "The agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Update an agent",
        "operationId": "updateAgent",
        "description": "Update an agent's profile, role or activation state.\n\n**Email and password cannot be changed here** — both answer `400` with\n`code: field_not_editable`. They are identity rather than profile: an email\nchange re-keys the global login index and must be confirmed from the address\nitself, and a password can only be set by the person who owns it.\n\nThe account's last Owner cannot be moved off Owner or deactivated. That answers\n`400` with `code: last_owner` — an account must never be able to lock itself out\nof its own product.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "role_id": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "department": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "two_factor_enabled": {
                    "type": "boolean"
                  }
                }
              },
              "examples": {
                "role": {
                  "summary": "Promote to a different role",
                  "value": {
                    "role_id": "F0qWvuztpIPYRLtcviaT"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Deactivate an agent",
        "operationId": "deleteAgent",
        "description": "Deactivate an agent.\n\nThey can no longer sign in and stop receiving assignments, but their name and\nhistory stay intact — a message has to keep showing who sent it. The seat is\nreleased at the next billing cycle.\n\nAny SSO permission naming this agent is removed at the same time, which\ninvalidates every SSO link already issued for them.",
        "responses": {
          "200": {
            "description": "Agent deactivated.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/DeletedResource"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "deactivated": {
                          "type": "boolean"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/ai-agents": {
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "List AI agents",
        "operationId": "listAiAgents",
        "description": "AI agent profiles, with every setting they carry. `agent_id` is the agent record each one fronts — that is what you assign a conversation to.",
        "responses": {
          "200": {
            "description": "AI agents returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AiAgent"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Create an AI agent",
        "operationId": "createAiAgent",
        "description": "Create an AI agent. ⚠️ **This may charge the card on file** — an AI agent costs\na seat exactly as a human one does, with the same `402` /\n`code: seat_charge_failed` behaviour and the same rollback.\n\nEvery field the console's AI agent editor offers is accepted and passed through:\npersona, instructions, model, language, the knowledge bases it may answer from,\nthe inboxes it works in and its hand-off rules. Unknown fields are rejected\nrather than silently dropped.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "persona": {
                    "type": "string"
                  },
                  "instructions": {
                    "type": "string"
                  },
                  "model": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "knowledge_base_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "channels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Inbox ids this agent works in."
                  },
                  "handoff": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "When and to whom it hands over to a human."
                  }
                },
                "additionalProperties": true
              },
              "examples": {
                "support": {
                  "summary": "A first-line support AI",
                  "value": {
                    "name": "Support AI",
                    "persona": "Friendly, concise, never guesses.",
                    "instructions": "Answer only from the product manuals. Hand off anything about refunds.",
                    "knowledge_base_ids": [
                      "kb_9f1"
                    ],
                    "language": "en"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "AI agent created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiAgent"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/ai-agents/{profile_id}": {
      "parameters": [
        {
          "name": "profile_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Get an AI agent",
        "operationId": "getAiAgent",
        "responses": {
          "200": {
            "description": "The AI agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiAgent"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Update an AI agent",
        "operationId": "updateAiAgent",
        "description": "Only the fields you send change.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated AI agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AiAgent"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Delete an AI agent",
        "operationId": "deleteAiAgent",
        "description": "Deletes the AI profile and deactivates the agent record fronting it. Conversations it handled keep their history; the seat is released at the next billing cycle.",
        "responses": {
          "200": {
            "description": "AI agent deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/teams": {
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "List teams",
        "operationId": "listTeams",
        "description": "Every team in the account. `?include=members` adds each team's roster.",
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Set to `members` to embed the roster.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Teams returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Team"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Create a team",
        "operationId": "createTeam",
        "description": "Create a team.\n\n`auto_assign_online: true` makes assigning the team immediately hand the\nconversation to a random online member — AI agents count as always online.\n`humans_only: true` keeps AI agents out of the team entirely.\n\nTeams are a plan capability: a plan without agent groups answers `402`. Names are\nunique per account, compared case-insensitively, so a duplicate answers `409`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "agent_ids": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "string"
                    }
                  },
                  "auto_assign_online": {
                    "type": "boolean"
                  },
                  "humans_only": {
                    "type": "boolean"
                  }
                }
              },
              "examples": {
                "sales": {
                  "summary": "A sales team with auto-assign",
                  "value": {
                    "name": "Sales",
                    "description": "Inbound sales enquiries",
                    "agent_ids": [
                      "agent_12",
                      "agent_45"
                    ],
                    "auto_assign_online": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Team created.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Team"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/teams/{team_id}": {
      "parameters": [
        {
          "name": "team_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Get a team",
        "operationId": "getTeam",
        "description": "One team, with its members resolved.",
        "responses": {
          "200": {
            "description": "The team.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Team"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Update a team",
        "operationId": "updateTeam",
        "description": "Only the fields you send change. Sending `agent_ids` replaces the whole roster.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "agent_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "auto_assign_online": {
                    "type": "boolean"
                  },
                  "humans_only": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated team.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Team"
                }
              }
            }
          },
          "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": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "Delete a team",
        "operationId": "deleteTeam",
        "description": "Conversations still assigned to the team are detached and return to the general waiting line rather than becoming unreachable. The response says how many.",
        "responses": {
          "200": {
            "description": "Team deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/DeletedResource"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "detached_conversations": {
                          "type": "integer"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/roles": {
      "get": {
        "tags": [
          "Agents & teams"
        ],
        "summary": "List roles",
        "operationId": "listRoles",
        "description": "The roles defined in this account, for use as `role_id` when creating or\nupdating an agent.\n\nRead-only. Roles decide what a *person* can reach in the console, and editing\nthat matrix from a machine credential is the kind of privilege change that\nshould leave a human's fingerprints on it.",
        "responses": {
          "200": {
            "description": "Roles returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Role"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/audit-log": {
      "get": {
        "tags": [
          "Audit log"
        ],
        "summary": "Read the audit log",
        "operationId": "listAuditLog",
        "description": "Audit entries, newest first.\n\n`action` accepts a full action (`agent.login`) or a prefix (`agent`), which\nmatches everything in that family. Use `from` and `to` to page through a long\nhistory: one call scans a bounded window, so an unfiltered request over a busy\nyear will not return everything — `meta.scan_truncated` tells you when that\nhappened.\n\nAnything done through this API carries `details.via = \"public_api\"` plus the\ncredential's `client_id` and name, and its `agent_id` reads\n`api:<credential_id>`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Full action or a prefix.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "agent_email",
            "in": "query",
            "required": false,
            "description": "Exact match on the actor's email.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Free text over action, actor and details.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "ISO-8601 lower bound on the timestamp.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "ISO-8601 upper bound (exclusive).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit entries returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AuditEntry"
                      }
                    },
                    "meta": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/PageMeta"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "scan_limit": {
                              "type": "integer"
                            },
                            "scan_truncated": {
                              "type": "boolean",
                              "description": "True when the scan window filled. Narrow the date range."
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/audit-log/actions": {
      "get": {
        "tags": [
          "Audit log"
        ],
        "summary": "List audit actions",
        "operationId": "listAuditActions",
        "description": "The distinct action names present in this account's log, with counts — so you can build a filter list without hardcoding names that vary by which features the account uses.",
        "responses": {
          "200": {
            "description": "Actions returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AuditEntry"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/billing/credits": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get credit balances",
        "operationId": "getCredits",
        "description": "The account's current credit balances.\n\n`monthly_balance` is what remains of this period's included credits and does not\nroll over; `topup_balance` is the total across every unexpired package. Spending\ndraws down the monthly balance first.",
        "responses": {
          "200": {
            "description": "Balances returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditBalance"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/billing/usage-pricing": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get the usage price list",
        "operationId": "listUsagePricing",
        "description": "What each metered action costs in credits: an outbound SMS, a WhatsApp template\nby category, a signing link.\n\nUse it to estimate a campaign before running it. Each row's `id` is the same\n`usage_item_id` that appears on a credit transaction, so costs reconcile after\nthe fact.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Filter by category.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match on name, description or id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Price list returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UsagePrice"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/billing/transactions": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "List credit transactions",
        "operationId": "listCreditTransactions",
        "description": "Credit movements, newest first — every spend, top-up and refund, with where the credits came from.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "Transactions returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CreditTransaction"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/billing/invoices": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "List invoices",
        "operationId": "listInvoices",
        "description": "Issued tax invoices, newest first.\n\nOnly issued documents appear. An invoice still being generated, or parked after a\nprovider rejection, is ours to resolve — it is not a row you should see and\nwonder about.\n\nThe PDF is not linked here: download URLs are minted per request and expire.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Lower bound on the issue date (YYYY-MM-DD).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Upper bound on the issue date (YYYY-MM-DD).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoices returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invoice"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/billing/invoices/{invoice_id}/download": {
      "parameters": [
        {
          "name": "invoice_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get an invoice download URL",
        "operationId": "downloadInvoice",
        "description": "A short-lived signed URL for one invoice PDF.\n\nMinted per call and valid for about an hour, so it is safe to hand to a browser\nbut should never be stored. Fetch a fresh one each time you need the file.",
        "responses": {
          "200": {
            "description": "A signed download URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "invoice_download"
                      ]
                    },
                    "invoice_id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/billing/plan": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get the current plan",
        "operationId": "getPlan",
        "description": "The plan this account is on: its ceilings and which features it includes.\n\nWorth reading once at the start of an integration. A `402` from anywhere else in\nthis API is explained by exactly one of these numbers or flags.",
        "responses": {
          "200": {
            "description": "The plan.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plan"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/files": {
      "get": {
        "tags": [
          "Files"
        ],
        "summary": "List files",
        "operationId": "listFiles",
        "description": "Files in the warehouse, newest first — attachments customers sent in, files agents sent out, and uploads from forms and knowledge bases.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "$ref": "#/components/parameters/SortDir"
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "incoming | outgoing | internal.",
            "schema": {
              "type": "string",
              "enum": [
                "incoming",
                "outgoing",
                "internal"
              ]
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "image | video | document | audio.",
            "schema": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "document",
                "audio"
              ]
            }
          },
          {
            "name": "conversation_id",
            "in": "query",
            "required": false,
            "description": "Only files from this conversation.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only files from this contact.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Substring match on the filename.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Files returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/File"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/PageMeta"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/files/stats": {
      "get": {
        "tags": [
          "Files"
        ],
        "summary": "Get storage statistics",
        "operationId": "getFileStats",
        "description": "Total files and bytes stored, against the plan's storage quota, broken down by\ncategory.\n\nThe quota comes back with the usage because a number with nothing to measure it\nagainst is why an upload starts failing \"for no reason\". `quota_bytes: null`\nmeans the plan has no ceiling.",
        "responses": {
          "200": {
            "description": "Statistics returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileStats"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/files/{file_id}": {
      "parameters": [
        {
          "name": "file_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Files"
        ],
        "summary": "Get a file",
        "operationId": "getFile",
        "description": "One file's metadata with a short-lived signed `download_url`. The URL expires within the hour and is minted per request — fetch a fresh one rather than storing it.",
        "responses": {
          "200": {
            "description": "The file.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Files"
        ],
        "summary": "Delete a file",
        "operationId": "deleteFile",
        "description": "Delete one file. The stored object goes with it and cannot be recovered.\n\nA message that referenced this file keeps its text but loses the attachment —\ncheck `conversation_id` on the file first if that matters.",
        "responses": {
          "200": {
            "description": "File deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/files/bulk-delete": {
      "post": {
        "tags": [
          "Files"
        ],
        "summary": "Delete many files",
        "operationId": "bulkDeleteFiles",
        "description": "Delete up to 100 files in one call.\n\nPartial success is normal and is reported rather than hidden: `deleted` lists the\nids that went and `failed` the ones that did not, with a reason. A file id that\ndoes not exist counts as failed — an integration deleting the wrong ids should\nfind out.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "file_ids"
                ],
                "properties": {
                  "file_ids": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "examples": {
                "cleanup": {
                  "summary": "Remove three files",
                  "value": {
                    "file_ids": [
                      "file_a1",
                      "file_b2",
                      "file_c3"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Processed. Check `failed` for anything that did not go.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "file_bulk_delete"
                      ]
                    },
                    "requested": {
                      "type": "integer"
                    },
                    "deleted": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "failed": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "reason": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "freed_bytes": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/agents/{agent_id}/profile": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get an agent's profile",
        "operationId": "getAgentProfile",
        "description": "One agent's personal settings: display name, timezone, language and picture.",
        "responses": {
          "200": {
            "description": "The profile.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentProfile"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Profile"
        ],
        "summary": "Update an agent's profile",
        "operationId": "updateAgentProfile",
        "description": "Update display name, timezone, language or contact details.\n\n`timezone` is an IANA name such as `Asia/Jerusalem`, and it is validated — a typo\nis a `400` rather than a profile that silently renders every timestamp in UTC.\n\nEmail, password and `role_id` are rejected here with `code: field_not_editable`.\nThe first two are identity, not profile; roles belong to\n`PATCH /v1/agents/{agent_id}` under the `agents_teams` scope.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "timezone": {
                    "type": "string",
                    "example": "Asia/Jerusalem"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "he"
                    ]
                  },
                  "phone": {
                    "type": "string"
                  },
                  "department": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              },
              "examples": {
                "tz": {
                  "summary": "Set the display timezone",
                  "value": {
                    "timezone": "Europe/London"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated profile.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentProfile"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/agents/{agent_id}/profile/avatar": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "post": {
        "tags": [
          "Profile"
        ],
        "summary": "Set a profile picture",
        "operationId": "uploadAgentAvatar",
        "description": "`multipart/form-data` with an `avatar` part — PNG, JPEG, GIF or WebP, up to 5 MB.\n\nThe upload is validated by decoding the image, not by trusting its\n`Content-Type`: a file that merely claims to be a PNG is rejected.\n\nThe returned `avatar_url` is an authenticated proxy path, never a public\nCloud Storage URL — a person's face should not be permanently addressable by\nanybody who once saw the link.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "avatar"
                ],
                "properties": {
                  "avatar": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Picture updated.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentProfile"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      },
      "delete": {
        "tags": [
          "Profile"
        ],
        "summary": "Remove a profile picture",
        "operationId": "deleteAgentAvatar",
        "description": "Removes the picture; the console falls back to the agent's initials.",
        "responses": {
          "200": {
            "description": "Picture removed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/agents/{agent_id}/notification-settings": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get notification settings",
        "operationId": "getNotificationSettings",
        "description": "How this agent is notified, plus the values each setting accepts.\n\n`channels` are the delivery routes (sound, email, push, bell) and `events` are\nwhat can trigger one. `available_channels`, `available_events` and\n`available_sounds` list what this build supports, so you never have to hardcode\nthem.",
        "responses": {
          "200": {
            "description": "Settings returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationSettings"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "tags": [
          "Profile"
        ],
        "summary": "Update notification settings",
        "operationId": "updateNotificationSettings",
        "description": "Replace an agent's notification settings.\n\nTurning the `push` channel off — or the master `enabled` switch — also deletes\nthat agent's stored browser push subscriptions, so the pushes actually stop\nrather than the toggle merely looking off.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "channels": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "boolean"
                    }
                  },
                  "events": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "boolean"
                    }
                  },
                  "sound": {
                    "type": "string"
                  }
                }
              },
              "examples": {
                "quiet": {
                  "summary": "Email only",
                  "value": {
                    "enabled": true,
                    "channels": {
                      "sound": false,
                      "push": false,
                      "email": true,
                      "bell": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings saved.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationSettings"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/agents/{agent_id}/notifications": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "List an agent's notifications",
        "operationId": "listNotifications",
        "description": "The notifications in one agent's bell, newest first.\n\nReading this **never marks anything as read**. In the console, opening the bell\nis a human deciding they have seen something; a background job polling for new\nitems must not clear that badge out from under the person it belongs to.\n\n`meta.unread_count` carries the badge number alongside the page.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          },
          {
            "name": "unread_only",
            "in": "query",
            "required": false,
            "description": "Only what the badge is counting.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Notifications returned.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Notification"
                      }
                    },
                    "meta": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/PageMeta"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "unread_count": {
                              "type": "integer"
                            },
                            "last_opened_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/agents/{agent_id}/notifications/unread-count": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "Get the unread count",
        "operationId": "getUnreadCount",
        "description": "Just the badge number — the cheap call to poll.",
        "responses": {
          "200": {
            "description": "The unread count.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "notification_unread_count"
                      ]
                    },
                    "agent_id": {
                      "type": "string"
                    },
                    "unread_count": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/sso/login": {
      "post": {
        "tags": [
          "SSO"
        ],
        "summary": "Create a single-use sign-in link",
        "operationId": "createSsoLink",
        "description": "Mint a link that signs one of your agents straight into the console — no login\nscreen, no password.\n\n### Before it will work\n\nThe `sso` scope alone grants nothing. In **Settings → API**, the credential must\nalso name:\n\n- **the agents** it may sign in as. An agent not on that list answers `403` with\n  `code: agent_not_allowed`, and the error lists who *is* allowed.\n- **the origins** allowed to embed the session, if you plan to open the link in\n  an iframe. Requesting `embed: true` with none configured answers `400` with\n  `code: no_embed_origins`.\n\n### The two modes\n\n**`full`** opens the whole console, exactly as if the agent had signed in.\n\n**`conversation`** opens one contact's chat and nothing else — no navigation, no\nconversation list. Supply the contact by `phone` or `email`. If a conversation\nwith them is already open it is opened; if not, the composer opens with the\ncontact pre-selected. Add `inbox_id` and the inbox is chosen too, leaving only\nthe message to write. This is the mode built for an iframe: open it, send a\nmessage, close it.\n\n### The link itself\n\nValid for **ten minutes** and redeemable **once** — a URL that bypasses the login\nscreen is a credential, and a credential in a URL ends up in browser history and\nreferrer headers. Mint one per use; do not cache it.\n\nRevocation is immediate: at redemption the credential and the agent are\nre-checked against live data, so removing an agent from the allowlist kills every\nlink already issued for them.\n\n### Embedding\n\nWith `embed: true` the resulting pages are served with `frame-ancestors` naming\nonly your configured origins, and the session cookie is issued\n`SameSite=None; Secure; Partitioned` so it lives in your site's own cookie\npartition and cannot be replayed from anywhere else.\n\nIn `conversation` mode the embedded page posts a message to the parent window\nwhen the agent sends something, so you can close the iframe without polling:\n\n```js\nwindow.addEventListener('message', (event) => {\n  if (event.origin !== 'https://console.teloring.com') return;\n  if (event.data?.source === 'teloring' && event.data.type === 'message_sent') {\n    closeMyIframe();\n  }\n});\n```",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "agent_id"
                ],
                "properties": {
                  "agent_id": {
                    "type": "string",
                    "description": "Must be on the credential's SSO agent list."
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "full",
                      "conversation"
                    ],
                    "default": "full"
                  },
                  "contact": {
                    "type": "object",
                    "description": "Required for `conversation` mode.",
                    "properties": {
                      "phone": {
                        "type": "string"
                      },
                      "email": {
                        "type": "string",
                        "format": "email"
                      }
                    }
                  },
                  "inbox_id": {
                    "type": "string",
                    "description": "Optional, `conversation` mode. Pre-selects the inbox."
                  },
                  "embed": {
                    "type": "boolean",
                    "default": false,
                    "description": "Set true when the link will be opened in an iframe."
                  }
                }
              },
              "examples": {
                "full": {
                  "summary": "Whole console",
                  "value": {
                    "agent_id": "agent_12",
                    "mode": "full"
                  }
                },
                "conversation": {
                  "summary": "One contact's chat, embedded",
                  "value": {
                    "agent_id": "agent_12",
                    "mode": "conversation",
                    "contact": {
                      "phone": "+972501234567"
                    },
                    "inbox_id": "3",
                    "embed": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Link created. Valid for ten minutes, once.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SsoLogin"
                }
              }
            }
          },
          "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"
          }
        }
      }
    }
  }
}
