{
  "info": {
    "name": "Teloring API v1.0.0",
    "description": "The Teloring REST API.\n\n**Setup:** open the collection's *Variables* tab, paste the `client_id` and `client_secret` from Settings → API, then run **Authentication → Get an access token**. Its test script stores the token, and every other request in this collection uses it automatically.\n\nTokens last one hour — re-run that request when calls start answering 401.\n\nFull reference: https://docs.teloring.com/api\n\n_Generated from docs/api/openapi.yaml — do not edit by hand._",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{access_token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.teloring.com/v1",
      "type": "string"
    },
    {
      "key": "client_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "client_secret",
      "value": "",
      "type": "string"
    },
    {
      "key": "access_token",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "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",
      "item": [
        {
          "name": "Get an access token",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/oauth/token",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "token"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"client_id\": \"tlc_811fc5491673d78d047a1085da2e22b7\",\n  \"client_secret\": \"tls_9f3c8a21b6d54e7f90a1c2b3d4e5f60718293a4b5c6d7e8f\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "auth": {
              "type": "noauth"
            }
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves the access token into the collection so every other request just works.",
                  "if (pm.response.code === 200) {",
                  "    const body = pm.response.json();",
                  "    pm.collectionVariables.set('access_token', body.access_token);",
                  "    console.log('Token saved. Expires in ' + body.expires_in + 's. Scopes: ' + (body.scopes || []).join(', '));",
                  "} else {",
                  "    console.error('Token request failed:', pm.response.text());",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Inspect the current token",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/oauth/introspect",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "introspect"
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List conversations",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations?status=&sort_by=&inbox_id=&inbox_type=&assignee_id=&team_id=&priority=&flag=&label=&contact_id=&customer_id=&pinned=&time_window=&updated_after=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "Which bucket to read.",
                  "disabled": true
                },
                {
                  "key": "sort_by",
                  "value": "",
                  "description": "Field to order by.",
                  "disabled": true
                },
                {
                  "key": "inbox_id",
                  "value": "",
                  "description": "One or more inbox ids.",
                  "disabled": true
                },
                {
                  "key": "inbox_type",
                  "value": "",
                  "description": "One or more channel types, e.g. `whatsapp`.",
                  "disabled": true
                },
                {
                  "key": "assignee_id",
                  "value": "",
                  "description": "Agent ids, or `unassigned` for the waiting line.",
                  "disabled": true
                },
                {
                  "key": "team_id",
                  "value": "",
                  "description": "Team ids, or `none` for conversations with no team.",
                  "disabled": true
                },
                {
                  "key": "priority",
                  "value": "",
                  "description": "low | medium | high | urgent.",
                  "disabled": true
                },
                {
                  "key": "flag",
                  "value": "",
                  "description": "Flag emoji values.",
                  "disabled": true
                },
                {
                  "key": "label",
                  "value": "",
                  "description": "Label names. A conversation matches if it carries any of them.",
                  "disabled": true
                },
                {
                  "key": "contact_id",
                  "value": "",
                  "description": "Only this contact's conversations.",
                  "disabled": true
                },
                {
                  "key": "customer_id",
                  "value": "",
                  "description": "Only this customer's conversations.",
                  "disabled": true
                },
                {
                  "key": "pinned",
                  "value": "",
                  "description": "Only pinned, or only unpinned.",
                  "disabled": true
                },
                {
                  "key": "time_window",
                  "value": "",
                  "description": "Shorthand for a created-at range.",
                  "disabled": true
                },
                {
                  "key": "updated_after",
                  "value": "",
                  "description": "Only conversations touched at or after this moment — the cheap way to poll for changes.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Create a conversation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"inbox_id\": \"3\",\n  \"contact\": {\n    \"phone\": \"+972501234567\",\n    \"name\": \"Dana Levi\"\n  },\n  \"priority\": \"high\",\n  \"message\": {\n    \"type\": \"text\",\n    \"content\": \"Hi Dana — your order has shipped.\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Queue counts",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/counts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                "counts"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get a conversation",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id"
              ]
            },
            "description": "Everything stored about one conversation, including its custom attributes."
          },
          "response": []
        },
        {
          "name": "Update a conversation",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"status\": \"resolved\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a conversation (email inboxes only)",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Put a conversation on hold",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/hold",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "hold"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"preset\": \"tomorrow_9am\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Release a hold",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/hold",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "hold"
              ]
            },
            "description": "Release a hold early and return the conversation to its queue."
          },
          "response": []
        },
        {
          "name": "Move the conversation to a different customer",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/customer",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "customer"
              ]
            },
            "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`.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customer_id\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Read a conversation's custom attributes",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/custom-attributes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "custom-attributes"
              ]
            },
            "description": "The attribute values stored on this conversation, with their definitions resolved."
          },
          "response": []
        },
        {
          "name": "Set custom attribute values",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/custom-attributes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "custom-attributes"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"values\": {\n    \"reason_for_contact\": \"billing\",\n    \"order_number\": \"SO-4192\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List inboxes",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/inboxes?type=&active=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "inboxes"
              ],
              "query": [
                {
                  "key": "type",
                  "value": "",
                  "description": "Filter to one channel type.",
                  "disabled": true
                },
                {
                  "key": "active",
                  "value": "",
                  "description": "Only enabled, or only disabled, inboxes.",
                  "disabled": true
                }
              ]
            },
            "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`."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List WhatsApp templates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/inboxes/:inbox_id/templates",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "inboxes",
                ":inbox_id",
                "templates"
              ],
              "variable": [
                {
                  "key": "inbox_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List messages",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/messages?order=&include_private=&direction=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "messages"
              ],
              "query": [
                {
                  "key": "order",
                  "value": "",
                  "description": "Chronological direction.",
                  "disabled": true
                },
                {
                  "key": "include_private",
                  "value": "",
                  "description": "Include internal notes.",
                  "disabled": true
                },
                {
                  "key": "direction",
                  "value": "",
                  "description": "Only inbound or only outbound.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Send a message",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/messages",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "messages"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"text\",\n  \"content\": \"Your order is on its way.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get a message",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/messages/:message_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "messages",
                ":message_id"
              ],
              "variable": [
                {
                  "key": "message_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "Delete a message",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversations/:conversation_id/messages/:message_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversations",
                ":conversation_id",
                "messages",
                ":message_id"
              ],
              "variable": [
                {
                  "key": "message_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List customers",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers?search=&lifecycle_stage=&tag=&assigned_agent=&sort_by=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers"
              ],
              "query": [
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match across the customer's text fields.",
                  "disabled": true
                },
                {
                  "key": "lifecycle_stage",
                  "value": "",
                  "description": "One or more stages, e.g. `lead`. Unknown stages are a 400 listing what this account uses.",
                  "disabled": true
                },
                {
                  "key": "tag",
                  "value": "",
                  "description": "One or more tags. Matches if the customer carries any of them.",
                  "disabled": true
                },
                {
                  "key": "assigned_agent",
                  "value": "",
                  "description": "Exact match on the assigned agent field.",
                  "disabled": true
                },
                {
                  "key": "sort_by",
                  "value": "",
                  "description": "Field to order by.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Create a customer",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Acme Ltd.\",\n  \"email\": \"hello@acme.example\",\n  \"phone\": \"+972501234567\",\n  \"lifecycle_stage\": \"lead\",\n  \"tags\": [\n    \"inbound\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Search customers",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/search?phone=&email=&q=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                "search"
              ],
              "query": [
                {
                  "key": "phone",
                  "value": "",
                  "description": "Exact phone match.",
                  "disabled": true
                },
                {
                  "key": "email",
                  "value": "",
                  "description": "Exact email match, case-insensitive.",
                  "disabled": true
                },
                {
                  "key": "q",
                  "value": "",
                  "description": "Free-text substring search.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get a customer",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id?include=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id"
              ],
              "query": [
                {
                  "key": "include",
                  "value": "",
                  "description": "Set to `contacts` to embed the linked contacts.",
                  "disabled": true
                }
              ]
            },
            "description": "One customer. Pass `include=contacts` to get its channel identities in the same call."
          },
          "response": []
        },
        {
          "name": "Update a customer",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id"
              ]
            },
            "description": "Only the fields you send change. Changing `lifecycle_stage` writes a journey event.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"lifecycle_stage\": \"customer\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a customer",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List a customer's contacts",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id/contacts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id",
                "contacts"
              ]
            },
            "description": "The channel identities linked to this customer — what you pass as `contact_id` when starting a conversation."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List object types",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/objects?include_disabled=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "objects"
              ],
              "query": [
                {
                  "key": "include_disabled",
                  "value": "",
                  "description": "Also return object types that are switched off.",
                  "disabled": true
                }
              ]
            },
            "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)."
          },
          "response": []
        },
        {
          "name": "Get an object type",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/objects/:object_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "objects",
                ":object_id"
              ]
            },
            "description": "One object type and its full field schema."
          },
          "response": []
        },
        {
          "name": "List records across all customers",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/objects/:object_id/records?customer_id=&field.stage=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "objects",
                ":object_id",
                "records"
              ],
              "query": [
                {
                  "key": "customer_id",
                  "value": "",
                  "description": "Narrow to one customer.",
                  "disabled": true
                },
                {
                  "key": "field.stage",
                  "value": "",
                  "description": "Match a field value exactly: `field.<key>=<value>`. Repeat for several fields.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List one customer's records",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id/objects/:object_id/records",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id",
                "objects",
                ":object_id",
                "records"
              ]
            },
            "description": "Records of one object type belonging to one customer."
          },
          "response": []
        },
        {
          "name": "Create a record",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id/objects/:object_id/records",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id",
                "objects",
                ":object_id",
                "records"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"data\": {\n    \"title\": \"Annual renewal\",\n    \"amount\": 12000,\n    \"stage\": \"Negotiation\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get a record",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id/objects/:object_id/records/:record_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id",
                "objects",
                ":object_id",
                "records",
                ":record_id"
              ],
              "variable": [
                {
                  "key": "record_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "Update a record",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id/objects/:object_id/records/:record_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id",
                "objects",
                ":object_id",
                "records",
                ":record_id"
              ],
              "variable": [
                {
                  "key": "record_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"data\": {\n    \"stage\": \"Won\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a record",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/customers/:customer_id/objects/:object_id/records/:record_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "customers",
                ":customer_id",
                "objects",
                ":object_id",
                "records",
                ":record_id"
              ],
              "variable": [
                {
                  "key": "record_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Deletes the record and removes any cross-object links pointing at it."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List dashboards",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/analytics/dashboards",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "analytics",
                "dashboards"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get a dashboard",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/analytics/dashboards/:dashboard_id?include=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "analytics",
                "dashboards",
                ":dashboard_id"
              ],
              "query": [
                {
                  "key": "include",
                  "value": "",
                  "description": "Set to `values` to compute every graph.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "dashboard_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List a dashboard's graphs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/analytics/dashboards/:dashboard_id/graphs?include=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "analytics",
                "dashboards",
                ":dashboard_id",
                "graphs"
              ],
              "query": [
                {
                  "key": "include",
                  "value": "",
                  "description": "Set to `values` to compute every graph.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "dashboard_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "The graphs on one dashboard. `?include=values` computes each one."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List flows",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/studio/flows?status=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "studio",
                "flows"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "Filter by state.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match on the flow name.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get a flow with its blocks",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/studio/flows/:flow_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "studio",
                "flows",
                ":flow_id"
              ],
              "variable": [
                {
                  "key": "flow_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List block and trigger types",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/studio/blocks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "studio",
                "blocks"
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List AI capabilities",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-world",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-world"
              ]
            },
            "description": "Every AI capability and whether it is switched on for this account."
          },
          "response": []
        },
        {
          "name": "Get one capability",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-world/:feature_key",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-world",
                ":feature_key"
              ],
              "variable": [
                {
                  "key": "feature_key",
                  "value": "",
                  "description": "From `GET /v1/ai-world`, e.g. `ai_copilot`."
                }
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "Switch a capability on or off",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-world/:feature_key",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-world",
                ":feature_key"
              ],
              "variable": [
                {
                  "key": "feature_key",
                  "value": "",
                  "description": "From `GET /v1/ai-world`, e.g. `ai_copilot`."
                }
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"enabled\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List knowledge bases",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases"
              ]
            },
            "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\"."
          },
          "response": []
        },
        {
          "name": "Create a knowledge base",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases"
              ]
            },
            "description": "Create an empty knowledge base. Counts against the plan's knowledge-base limit.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Product manuals\",\n  \"description\": \"Everything the support AI may quote.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get a knowledge base",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases/:kb_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases",
                ":kb_id"
              ],
              "variable": [
                {
                  "key": "kb_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "One knowledge base with its indexing statistics."
          },
          "response": []
        },
        {
          "name": "Delete a knowledge base",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases/:kb_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases",
                ":kb_id"
              ],
              "variable": [
                {
                  "key": "kb_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List sources",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases/:kb_id/sources?status=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases",
                ":kb_id",
                "sources"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "Filter by ingestion state.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "kb_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Add a source",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases/:kb_id/sources",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases",
                ":kb_id",
                "sources"
              ],
              "variable": [
                {
                  "key": "kb_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://help.example.com/\",\n  \"crawl_inner\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a source",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases/:kb_id/sources/:source_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases",
                ":kb_id",
                "sources",
                ":source_id"
              ],
              "variable": [
                {
                  "key": "kb_id",
                  "value": "",
                  "description": ""
                },
                {
                  "key": "source_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Deletes one source and every chunk derived from it."
          },
          "response": []
        },
        {
          "name": "List indexed chunks",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/knowledge-bases/:kb_id/chunks?source_id=&include_content=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "knowledge-bases",
                ":kb_id",
                "chunks"
              ],
              "query": [
                {
                  "key": "source_id",
                  "value": "",
                  "description": "Only chunks from this source.",
                  "disabled": true
                },
                {
                  "key": "include_content",
                  "value": "",
                  "description": "Return the passage text.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "kb_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List quick replies",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/quick-replies?scope=&agent_id=&category_id=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "quick-replies"
              ],
              "query": [
                {
                  "key": "scope",
                  "value": "",
                  "description": "account | personal.",
                  "disabled": true
                },
                {
                  "key": "agent_id",
                  "value": "",
                  "description": "One agent's personal replies.",
                  "disabled": true
                },
                {
                  "key": "category_id",
                  "value": "",
                  "description": "Only replies in this category.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match on title and body.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Create a quick reply",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/quick-replies",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "quick-replies"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"Refund policy\",\n  \"body\": \"Hi {{contact.name}}, our refund window is 14 days from delivery.\",\n  \"scope\": \"account\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List categories",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/quick-replies/categories",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "quick-replies",
                "categories"
              ]
            },
            "description": "The categories quick replies can be filed under."
          },
          "response": []
        },
        {
          "name": "Get a quick reply",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/quick-replies/:quick_reply_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "quick-replies",
                ":quick_reply_id"
              ],
              "variable": [
                {
                  "key": "quick_reply_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "Update a quick reply",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/quick-replies/:quick_reply_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "quick-replies",
                ":quick_reply_id"
              ],
              "variable": [
                {
                  "key": "quick_reply_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Only the fields you send change.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"\",\n  \"body\": \"\",\n  \"scope\": \"account\",\n  \"category_id\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a quick reply",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/quick-replies/:quick_reply_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "quick-replies",
                ":quick_reply_id"
              ],
              "variable": [
                {
                  "key": "quick_reply_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List forms",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/forms?status=&type=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "forms"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "Filter by publication state.",
                  "disabled": true
                },
                {
                  "key": "type",
                  "value": "",
                  "description": "Filter by form type.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match on the form name.",
                  "disabled": true
                }
              ]
            },
            "description": "Every form in the account, with its submission count and public URL."
          },
          "response": []
        },
        {
          "name": "Get a form",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/forms/:form_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "forms",
                ":form_id"
              ],
              "variable": [
                {
                  "key": "form_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Delete a form",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/forms/:form_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "forms",
                ":form_id"
              ],
              "variable": [
                {
                  "key": "form_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List a form's submissions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/forms/:form_id/submissions?search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "forms",
                ":form_id",
                "submissions"
              ],
              "query": [
                {
                  "key": "search",
                  "value": "",
                  "description": "Free-text search over the submitted values.",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "form_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "List submissions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/form-submissions?form_id=&contact_id=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "form-submissions"
              ],
              "query": [
                {
                  "key": "form_id",
                  "value": "",
                  "description": "Only this form's submissions.",
                  "disabled": true
                },
                {
                  "key": "contact_id",
                  "value": "",
                  "description": "Only submissions linked to this contact.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Free-text search over the submitted values.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get a submission",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/form-submissions/:submission_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "form-submissions",
                ":submission_id"
              ],
              "variable": [
                {
                  "key": "submission_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List documents",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/signature/documents?status=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signature",
                "documents"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "draft | active.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Upload a PDF",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/signature/documents",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signature",
                "documents"
              ]
            },
            "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.",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": [],
                  "description": "The PDF."
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "List signing links",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/signature/links?status=&document_id=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signature",
                "links"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "pending | signed | declined | expired.",
                  "disabled": true
                },
                {
                  "key": "document_id",
                  "value": "",
                  "description": "Only links for this document.",
                  "disabled": true
                }
              ]
            },
            "description": "Signing links. `status=pending` is the waiting-to-sign list."
          },
          "response": []
        },
        {
          "name": "Create a signing link",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/signature/links",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signature",
                "links"
              ]
            },
            "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).",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"document_id\": \"doc_9f1\",\n  \"customer_id\": \"44\",\n  \"contact_id\": \"42\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Revoke a signing link",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/signature/links/:link_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signature",
                "links",
                ":link_id"
              ],
              "variable": [
                {
                  "key": "link_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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`."
          },
          "response": []
        },
        {
          "name": "List signed documents",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/signature/signed-documents?status=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signature",
                "signed-documents"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "",
                  "description": "completed | declined.",
                  "disabled": true
                }
              ]
            },
            "description": "Completed and declined signings, newest first. A declined signing carries the reason the signer gave."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "Get account details",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/account",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "account"
              ]
            },
            "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`"
          },
          "response": []
        },
        {
          "name": "Update account details",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/account",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "account"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"business_tax_id\": \"514123456\",\n  \"business_address\": \"12 Rothschild Blvd\",\n  \"business_city\": \"Tel Aviv\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List business-hours schedules",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/business-hours",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "business-hours"
              ]
            },
            "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`"
          },
          "response": []
        },
        {
          "name": "Create a schedule",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/business-hours",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "business-hours"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Support hours\",\n  \"timezone\": \"Asia/Jerusalem\",\n  \"days\": {\n    \"sunday\": [\n      {\n        \"start\": \"09:00\",\n        \"end\": \"17:00\"\n      }\n    ],\n    \"monday\": [\n      {\n        \"start\": \"09:00\",\n        \"end\": \"17:00\"\n      }\n    ],\n    \"tuesday\": [\n      {\n        \"start\": \"09:00\",\n        \"end\": \"17:00\"\n      }\n    ],\n    \"wednesday\": [\n      {\n        \"start\": \"09:00\",\n        \"end\": \"17:00\"\n      }\n    ],\n    \"thursday\": [\n      {\n        \"start\": \"09:00\",\n        \"end\": \"17:00\"\n      }\n    ],\n    \"friday\": [],\n    \"saturday\": []\n  },\n  \"consider_holidays\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Update a schedule",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/business-hours/:schedule_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "business-hours",
                ":schedule_id"
              ],
              "variable": [
                {
                  "key": "schedule_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "System schedules cannot be edited — those answer `403` with `code: system_schedule`.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a schedule",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/business-hours/:schedule_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "business-hours",
                ":schedule_id"
              ],
              "variable": [
                {
                  "key": "schedule_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List holiday calendars",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/holidays?year=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "holidays"
              ],
              "query": [
                {
                  "key": "year",
                  "value": "",
                  "description": "Four-digit year. Defaults to the current one.",
                  "disabled": true
                }
              ]
            },
            "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`"
          },
          "response": []
        },
        {
          "name": "Get the conversation-attribute schema",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/conversation-attributes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "conversation-attributes"
              ]
            },
            "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`"
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List agents",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents?type=&active=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents"
              ],
              "query": [
                {
                  "key": "type",
                  "value": "",
                  "description": "human | ai.",
                  "disabled": true
                },
                {
                  "key": "active",
                  "value": "",
                  "description": "Only active, or only deactivated, agents.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match on name and email.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Create a human agent",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"dana@example.com\",\n  \"name\": \"Dana Levi\",\n  \"role_id\": \"TegbEuzpFS4MvIlTOxBz\",\n  \"department\": \"Support\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get an agent",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id"
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "Update an agent",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"role_id\": \"F0qWvuztpIPYRLtcviaT\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Deactivate an agent",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List AI agents",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-agents",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-agents"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Create an AI agent",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-agents",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-agents"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Support AI\",\n  \"persona\": \"Friendly, concise, never guesses.\",\n  \"instructions\": \"Answer only from the product manuals. Hand off anything about refunds.\",\n  \"knowledge_base_ids\": [\n    \"kb_9f1\"\n  ],\n  \"language\": \"en\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get an AI agent",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-agents/:profile_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-agents",
                ":profile_id"
              ],
              "variable": [
                {
                  "key": "profile_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": ""
          },
          "response": []
        },
        {
          "name": "Update an AI agent",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-agents/:profile_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-agents",
                ":profile_id"
              ],
              "variable": [
                {
                  "key": "profile_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Only the fields you send change.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete an AI agent",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/ai-agents/:profile_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "ai-agents",
                ":profile_id"
              ],
              "variable": [
                {
                  "key": "profile_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List teams",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/teams?include=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "teams"
              ],
              "query": [
                {
                  "key": "include",
                  "value": "",
                  "description": "Set to `members` to embed the roster.",
                  "disabled": true
                }
              ]
            },
            "description": "Every team in the account. `?include=members` adds each team's roster."
          },
          "response": []
        },
        {
          "name": "Create a team",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/teams",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "teams"
              ]
            },
            "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`.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Sales\",\n  \"description\": \"Inbound sales enquiries\",\n  \"agent_ids\": [\n    \"agent_12\",\n    \"agent_45\"\n  ],\n  \"auto_assign_online\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get a team",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/teams/:team_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "teams",
                ":team_id"
              ],
              "variable": [
                {
                  "key": "team_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "One team, with its members resolved."
          },
          "response": []
        },
        {
          "name": "Update a team",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/teams/:team_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "teams",
                ":team_id"
              ],
              "variable": [
                {
                  "key": "team_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "description": "Only the fields you send change. Sending `agent_ids` replaces the whole roster.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"\",\n  \"description\": \"\",\n  \"agent_ids\": [\n    \"\"\n  ],\n  \"auto_assign_online\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a team",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/teams/:team_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "teams",
                ":team_id"
              ],
              "variable": [
                {
                  "key": "team_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List roles",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/roles",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "roles"
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "Read the audit log",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/audit-log?action=&agent_email=&search=&from=&to=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "audit-log"
              ],
              "query": [
                {
                  "key": "action",
                  "value": "",
                  "description": "Full action or a prefix.",
                  "disabled": true
                },
                {
                  "key": "agent_email",
                  "value": "",
                  "description": "Exact match on the actor's email.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Free text over action, actor and details.",
                  "disabled": true
                },
                {
                  "key": "from",
                  "value": "",
                  "description": "ISO-8601 lower bound on the timestamp.",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "",
                  "description": "ISO-8601 upper bound (exclusive).",
                  "disabled": true
                }
              ]
            },
            "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>`."
          },
          "response": []
        },
        {
          "name": "List audit actions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/audit-log/actions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "audit-log",
                "actions"
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "Get credit balances",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/billing/credits",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "billing",
                "credits"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get the usage price list",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/billing/usage-pricing?category=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "billing",
                "usage-pricing"
              ],
              "query": [
                {
                  "key": "category",
                  "value": "",
                  "description": "Filter by category.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match on name, description or id.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "List credit transactions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/billing/transactions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "billing",
                "transactions"
              ]
            },
            "description": "Credit movements, newest first — every spend, top-up and refund, with where the credits came from."
          },
          "response": []
        },
        {
          "name": "List invoices",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/billing/invoices?search=&from=&to=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "billing",
                "invoices"
              ],
              "query": [
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match.",
                  "disabled": true
                },
                {
                  "key": "from",
                  "value": "",
                  "description": "Lower bound on the issue date (YYYY-MM-DD).",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "",
                  "description": "Upper bound on the issue date (YYYY-MM-DD).",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get an invoice download URL",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/billing/invoices/:invoice_id/download",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "billing",
                "invoices",
                ":invoice_id",
                "download"
              ],
              "variable": [
                {
                  "key": "invoice_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get the current plan",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/billing/plan",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "billing",
                "plan"
              ]
            },
            "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."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List files",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/files?direction=&category=&conversation_id=&contact_id=&search=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "files"
              ],
              "query": [
                {
                  "key": "direction",
                  "value": "",
                  "description": "incoming | outgoing | internal.",
                  "disabled": true
                },
                {
                  "key": "category",
                  "value": "",
                  "description": "image | video | document | audio.",
                  "disabled": true
                },
                {
                  "key": "conversation_id",
                  "value": "",
                  "description": "Only files from this conversation.",
                  "disabled": true
                },
                {
                  "key": "contact_id",
                  "value": "",
                  "description": "Only files from this contact.",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Substring match on the filename.",
                  "disabled": true
                }
              ]
            },
            "description": "Files in the warehouse, newest first — attachments customers sent in, files agents sent out, and uploads from forms and knowledge bases."
          },
          "response": []
        },
        {
          "name": "Get storage statistics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/files/stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "files",
                "stats"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get a file",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/files/:file_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "files",
                ":file_id"
              ],
              "variable": [
                {
                  "key": "file_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Delete a file",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/files/:file_id",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "files",
                ":file_id"
              ],
              "variable": [
                {
                  "key": "file_id",
                  "value": "",
                  "description": ""
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Delete many files",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/files/bulk-delete",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "files",
                "bulk-delete"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"file_ids\": [\n    \"file_a1\",\n    \"file_b2\",\n    \"file_c3\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "Get an agent's profile",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/profile",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "profile"
              ]
            },
            "description": "One agent's personal settings: display name, timezone, language and picture."
          },
          "response": []
        },
        {
          "name": "Update an agent's profile",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/profile",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "profile"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"timezone\": \"Europe/London\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Set a profile picture",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/profile/avatar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "profile",
                "avatar"
              ]
            },
            "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.",
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "avatar",
                  "type": "file",
                  "src": [],
                  "description": ""
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "Remove a profile picture",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/profile/avatar",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "profile",
                "avatar"
              ]
            },
            "description": "Removes the picture; the console falls back to the agent's initials."
          },
          "response": []
        },
        {
          "name": "Get notification settings",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/notification-settings",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "notification-settings"
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Update notification settings",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/notification-settings",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "notification-settings"
              ]
            },
            "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.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"enabled\": true,\n  \"channels\": {\n    \"sound\": false,\n    \"push\": false,\n    \"email\": true,\n    \"bell\": true\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "List an agent's notifications",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/notifications?unread_only=",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "notifications"
              ],
              "query": [
                {
                  "key": "unread_only",
                  "value": "",
                  "description": "Only what the badge is counting.",
                  "disabled": true
                }
              ]
            },
            "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."
          },
          "response": []
        },
        {
          "name": "Get the unread count",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/agents/:agent_id/notifications/unread-count",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "agents",
                ":agent_id",
                "notifications",
                "unread-count"
              ]
            },
            "description": "Just the badge number — the cheap call to poll."
          },
          "response": []
        }
      ]
    },
    {
      "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",
      "item": [
        {
          "name": "Create a single-use sign-in link",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/sso/login",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "sso",
                "login"
              ]
            },
            "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```",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"agent_id\": \"agent_12\",\n  \"mode\": \"full\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    }
  ]
}
