{
  "info": {
    "_postman_id": "6b1f0c4e-8a35-4d71-9f2a-1c0d5e7b4a92",
    "name": "Mirai Voice API (v2)",
    "description": "Every public endpoint of the Mirai Voice v2 API, with a worked example beside each one.\n\n**This file is generated from the API itself.** Each release of the API ships this collection with it, and the release cannot go out if a public route is missing from it. Download it again from the console (Developers → Postman) whenever you want the latest.\n\n**Set up once.** Import this collection and one environment, select the environment, then fill in two values:\n\n* `api_key`: mint one on the console's Developers page. It is shown once. Only its hash is stored, so a lost key gets rotated, not recovered.\n* `test_number`: the phone you want calls to ring, in E.164 (`+919876543210`).\n\nThere are two environments and the requests are the same in both. Only `base_url` changes:\n\n* **sandbox** (`https://sandbox.voice.miraiminds.co`) is for trial workspaces.\n* **production** (`https://prod.voice.miraiminds.co`) is for workspaces that have gone live.\n\nThe console's Developers page hands you the right one with your key already in it.\n\nAuth is set once for the whole collection (`Authorization: Bearer {{api_key}}`), so no request carries a key of its own. Requests that create something (an agent, a call, a campaign) save the new id into a collection variable, so the next request in the folder just works.\n\n**How it fits together.** Create an agent, place a call, then read the call. Placing a call answers `202` with an id, because the call hasn't happened yet. Errors carry a stable code, so you can branch on it without parsing prose: `{\"error\": {\"code\", \"message\"}}` almost everywhere, and `{\"error\": \"<code>\", \"details\": [...]}` when a flow or a tool fails validation, with one entry per problem.\n\nFull reference: https://docs.miraiminds.co/api-reference/introduction (every endpoint) and https://docs.miraiminds.co/v2/start-building (guides)",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "Agents",
      "description": "An agent is what a call runs: its prompt (or a node flow, see the Flows folder), voice, language and limits. Write it once and dial it as often as you like; each call fills in its own `variables`.\n\nEvery save creates a new revision. You can read old revisions, roll back to one, and publish a draft when it is ready. None of the requests here place a call or charge your wallet.",
      "item": [
        {
          "name": "Create agent",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "service-reminder-agent-v1",
                "description": "Optional. Up to 255 characters. Reuse it only to retry the same request.",
                "disabled": true
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"language\": \"hi\",\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates an agent. Nothing is dialled and nothing is charged.\n\n`name`, `system_prompt`, `first_message` and `language` are required. Everything else has a working default, and the response shows every default it filled in. `{{name}}`-style placeholders in the prompts are filled from each call's `variables`.\n\n`voice.voice_id` must be a voice that `GET /v2/voices` lists. Anything else is a 400 that names the voices you can use. `secondary_languages` are other languages your callers may switch to; speech recognition listens for them too.\n\n`keyterms` are names and words your callers say that are easy to mishear: your brand, products, places or people. Up to 100, each 1–50 characters and at most five words, no commas; repeats in any case are dropped. Speech recognition listens for them on every call, and the agent's prompt names them.\n\nTurn on the `Idempotency-Key` header to make retries safe. Sending the same key again returns the agent it first created (200, with `Idempotent-Replay: true`) instead of a second agent. The same key with a different body is a 409."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_id = pick(\"id\");",
                  "  if (agent_id != null && agent_id !== '') pm.collectionVariables.set(\"agent_id\", String(agent_id));",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — created",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "service-reminder-agent-v1",
                    "description": "Optional. Up to 255 characters. Reuse it only to retry the same request.",
                    "disabled": true
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"language\": \"hi\",\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 1,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:14:02Z\"\n}"
            },
            {
              "name": "400 — a voice the platform does not have",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "service-reminder-agent-v1",
                    "description": "Optional. Up to 255 characters. Reuse it only to retry the same request.",
                    "disabled": true
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"language\": \"hi\",\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"unknown voice_id \\\"anushka\\\" — voice.voice_id must be one of ashu, neha, sameer, shruti\"\n  }\n}"
            },
            {
              "name": "401 — no key, or a wrong one",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "service-reminder-agent-v1",
                    "description": "Optional. Up to 255 characters. Reuse it only to retry the same request.",
                    "disabled": true
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"language\": \"hi\",\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"unauthorized\",\n    \"message\": \"Unknown or invalid key.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List agents",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "archived",
                  "value": "false",
                  "disabled": true
                }
              ]
            },
            "description": "Your agents, newest first, each one the full agent object. `limit` is 1–100 (default 20). When `has_more` is true, send `next_cursor` back as `cursor` for the next page.\n\n`archived=true` lists only archived agents and `archived=false` only active ones. Leave it out to get both. Deleted agents never appear."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "disabled": true
                    },
                    {
                      "key": "archived",
                      "value": "false",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"revision\": 1,\n      \"draft\": false,\n      \"archived\": false,\n      \"analysis\": {\n        \"enabled\": false\n      },\n      \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"object\": \"agent\",\n      \"name\": \"सर्विस रिमाइंडर\",\n      \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n      \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n      \"voice\": {\n        \"voice_id\": \"ashu\",\n        \"language\": \"hi\"\n      },\n      \"language\": \"hi\",\n      \"max_duration_secs\": 300,\n      \"end_call\": {\n        \"enabled\": true,\n        \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n        \"confirm\": true\n      },\n      \"voicemail\": {\n        \"action\": \"hangup\"\n      },\n      \"background_sound\": {\n        \"sound\": \"off\"\n      },\n      \"behavior\": {\n        \"interruptions\": \"normal\",\n        \"adaptive_interruptions\": true,\n        \"pass_through\": [],\n        \"date_awareness\": true\n      },\n      \"secondary_languages\": [\n        \"en\"\n      ],\n      \"keyterms\": [\n        \"मिराई मोटर्स\",\n        \"Swift\",\n        \"आशु\"\n      ],\n      \"tools\": [],\n      \"created_at\": \"2026-08-11T09:14:02Z\",\n      \"updated_at\": \"2026-08-11T09:14:02Z\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            },
            {
              "name": "400 — limit out of range",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "disabled": true
                    },
                    {
                      "key": "archived",
                      "value": "false",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"limit must be between 1 and 100\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get agent",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}"
              ]
            },
            "description": "One agent, with its current `revision`. An id that does not exist, was deleted or belongs to another workspace is a 404, and all three look the same."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — the agent",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 1,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:14:02Z\"\n}"
            },
            {
              "name": "404 — not yours, deleted, or never existed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no agent agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Update agent",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n  \"voice\": {\n    \"voice_id\": \"neha\",\n    \"language\": \"hi\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Send only the fields you are changing. Each save is a new revision.\n\nNested objects (`voice`, `end_call`, `voicemail`, `background_sound`, `analysis`) are replaced whole, and so are the `tools` list and the `flow` graph, so send the complete object. `behavior` is the exception: it merges field by field, and `behavior.pass_through` (words that never interrupt the agent) replaces the whole list you send. So does `keyterms`; send `[]` to clear it.\n\nTo refuse a stale edit, add `\"if_revision\"` with the revision you read. If someone saved the agent in between, you get a 409 and nothing changes.\n\n`{\"archived\": true}` stops new calls without deleting the agent, and `{\"archived\": false}` brings it back. Changes apply from the next call; calls already queued or running keep the version they started with."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — the updated agent",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n  \"voice\": {\n    \"voice_id\": \"neha\",\n    \"language\": \"hi\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 2,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n  \"voice\": {\n    \"voice_id\": \"neha\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:22:10Z\"\n}"
            },
            {
              "name": "409 — someone saved the agent since you read it",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n  \"voice\": {\n    \"voice_id\": \"neha\",\n    \"language\": \"hi\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"agent changed; read its current revision and retry\"\n  }\n}"
            },
            {
              "name": "400 — a field that does not exist",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n  \"voice\": {\n    \"voice_id\": \"neha\",\n    \"language\": \"hi\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"invalid JSON body: json: unknown field \\\"greeting\\\"\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Preview agent",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/preview",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "preview"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Fills the agent's prompts with a set of `variables` and returns the text a call would start with. Nothing is saved, dialled or charged, so it is a cheap way to check your variables before a campaign.\n\nAdd `changes` (any fields `PATCH` accepts) to preview an edit before you save it. If the agent has an `input_schema`, the values are checked against it and its defaults are filled in. Without one, every value must be a string, and a placeholder with no value renders empty."
          },
          "response": [
            {
              "name": "200 — the rendered text",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/preview",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "preview"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"agent_revision\": 2,\n  \"archived\": false,\n  \"draft\": false,\n  \"end_message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n  \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. राहुल जी की स्विफ्ट की सर्विस 18 अगस्त को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"variables\": {\n    \"due_date\": \"18 अगस्त\",\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\"\n  }\n}"
            },
            {
              "name": "400 — a number, with no input_schema to say it may be one",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/preview",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "preview"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"variables[\\\"visits\\\"] must be a string without input_schema\"\n  }\n}"
            },
            {
              "name": "404 — no such agent",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/preview",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "preview"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List revisions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "revisions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "Every saved version of the agent, newest first. Each item is the full agent exactly as it was saved at that revision. `limit` is 1–100 (default 20). When `has_more` is true, send `next_cursor` back as `cursor`; it is the revision number the next page starts at."
          },
          "response": [
            {
              "name": "200 — newest first",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "revisions"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"revision\": 2,\n      \"draft\": false,\n      \"archived\": false,\n      \"analysis\": {\n        \"enabled\": false\n      },\n      \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"object\": \"agent\",\n      \"name\": \"सर्विस रिमाइंडर\",\n      \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n      \"first_message\": \"नमस्ते, आशु बोल रहा हूं. सर्विस की बात करनी थी.\",\n      \"voice\": {\n        \"voice_id\": \"neha\",\n        \"language\": \"hi\"\n      },\n      \"language\": \"hi\",\n      \"max_duration_secs\": 300,\n      \"end_call\": {\n        \"enabled\": true,\n        \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n        \"confirm\": true\n      },\n      \"voicemail\": {\n        \"action\": \"hangup\"\n      },\n      \"background_sound\": {\n        \"sound\": \"off\"\n      },\n      \"behavior\": {\n        \"interruptions\": \"normal\",\n        \"adaptive_interruptions\": true,\n        \"pass_through\": [],\n        \"date_awareness\": true\n      },\n      \"secondary_languages\": [\n        \"en\"\n      ],\n      \"keyterms\": [\n        \"मिराई मोटर्स\",\n        \"Swift\",\n        \"आशु\"\n      ],\n      \"tools\": [],\n      \"created_at\": \"2026-08-11T09:14:02Z\",\n      \"updated_at\": \"2026-08-11T09:22:10Z\"\n    },\n    {\n      \"revision\": 1,\n      \"draft\": false,\n      \"archived\": false,\n      \"analysis\": {\n        \"enabled\": false\n      },\n      \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"object\": \"agent\",\n      \"name\": \"सर्विस रिमाइंडर\",\n      \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n      \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n      \"voice\": {\n        \"voice_id\": \"ashu\",\n        \"language\": \"hi\"\n      },\n      \"language\": \"hi\",\n      \"max_duration_secs\": 300,\n      \"end_call\": {\n        \"enabled\": true,\n        \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n        \"confirm\": true\n      },\n      \"voicemail\": {\n        \"action\": \"hangup\"\n      },\n      \"background_sound\": {\n        \"sound\": \"off\"\n      },\n      \"behavior\": {\n        \"interruptions\": \"normal\",\n        \"adaptive_interruptions\": true,\n        \"pass_through\": [],\n        \"date_awareness\": true\n      },\n      \"secondary_languages\": [\n        \"en\"\n      ],\n      \"keyterms\": [\n        \"मिराई मोटर्स\",\n        \"Swift\",\n        \"आशु\"\n      ],\n      \"tools\": [],\n      \"created_at\": \"2026-08-11T09:14:02Z\",\n      \"updated_at\": \"2026-08-11T09:14:02Z\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": \"\"\n}"
            },
            {
              "name": "404 — no such agent",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "revisions"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get revision",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions/{{revision}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "revisions",
                "{{revision}}"
              ]
            },
            "description": "One saved revision, exactly as it was. Revisions never change. To run a call on a particular revision instead of the current one, pass `agent_revision` to `POST /v2/calls`."
          },
          "response": [
            {
              "name": "200 — revision 1",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions/{{revision}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "revisions",
                    "{{revision}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 1,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:14:02Z\"\n}"
            },
            {
              "name": "404 — no such revision",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions/{{revision}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "revisions",
                    "{{revision}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"revision not found\"\n  }\n}"
            },
            {
              "name": "400 — not a revision number",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/revisions/{{revision}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "revisions",
                    "{{revision}}"
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"revision must be a positive integer\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Roll back to a revision",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/rollback",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "rollback"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": {{agent_revision}},\n  \"revision\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Copies an old revision's configuration into a new **draft** revision. The agent keeps its id, name and archive state. A draft takes no ordinary calls; try it with a browser test call (`channel: \"web\"` and `test: true` on `POST /v2/calls`), then publish it.\n\nBoth fields are required. `if_revision` is the agent's current revision; the collection keeps it in `{{agent_revision}}` from the last response that returned the agent. `revision` is the one to copy."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — revision 1, as a new draft",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/rollback",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "rollback"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": {{agent_revision}},\n  \"revision\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 3,\n  \"draft\": true,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:30:04Z\"\n}"
            },
            {
              "name": "409 — someone saved the agent since you read it",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/rollback",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "rollback"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": {{agent_revision}},\n  \"revision\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"agent changed; read its current revision and retry\"\n  }\n}"
            },
            {
              "name": "404 — no such revision",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/rollback",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "rollback"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": {{agent_revision}},\n  \"revision\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"revision not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Publish agent",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/publish",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "publish"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": {{agent_revision}}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Publishes the current draft. The agent is checked as if it were about to take a call and saved as a new revision that is no longer a draft, so ordinary calls can use it again.\n\n`if_revision` is required and must be the agent's current revision, which the collection keeps in `{{agent_revision}}`. An archived agent has to be restored first."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — published",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/publish",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "publish"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": {{agent_revision}}\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 4,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:31:12Z\"\n}"
            },
            {
              "name": "409 — someone saved the agent since you read it",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/publish",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "publish"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": {{agent_revision}}\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"agent changed; read its current revision and retry\"\n  }\n}"
            },
            {
              "name": "409 — archived",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/publish",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "publish"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": {{agent_revision}}\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"agent_archived\",\n    \"message\": \"restore this agent before publishing\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List agent logs",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/logs?part=tools&limit=50",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "logs"
              ],
              "query": [
                {
                  "key": "part",
                  "value": "tools"
                },
                {
                  "key": "level",
                  "value": "error",
                  "disabled": true
                },
                {
                  "key": "name",
                  "value": "create_complaint",
                  "disabled": true
                },
                {
                  "key": "call_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "since",
                  "value": "2026-10-11T09:00:00Z",
                  "disabled": true
                },
                {
                  "key": "until",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "What happened on this agent's calls, newest first: tool runs, tools the agent asked for that it does not have, the variables each call got, how the post-call results went, and each call starting and ending. It is the same list as the Logs tab in Agent Studio.\n\nEvery filter is optional. `part` is `prompt`, `tools`, `variables`, `results` or `calls`. `level` is `error` or `warning`. `name` narrows it to one tool, variable or result field, and `call_id` to one call. `since` and `until` are RFC 3339 times. `limit` is up to 200. When `next_cursor` is set, send it back as `cursor` for the next page.\n\nEach item has a one-line `summary` you can show as is, and `detail` with the full record: request and response for a tool run (secrets and headers masked), the values a call got, and so on."
          },
          "response": [
            {
              "name": "200 — a failing tool and a tool the prompt names",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/logs?part=tools&limit=50",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "logs"
                  ],
                  "query": [
                    {
                      "key": "part",
                      "value": "tools"
                    },
                    {
                      "key": "level",
                      "value": "error",
                      "disabled": true
                    },
                    {
                      "key": "name",
                      "value": "create_complaint",
                      "disabled": true
                    },
                    {
                      "key": "call_id",
                      "value": "",
                      "disabled": true
                    },
                    {
                      "key": "since",
                      "value": "2026-10-11T09:00:00Z",
                      "disabled": true
                    },
                    {
                      "key": "until",
                      "value": "",
                      "disabled": true
                    },
                    {
                      "key": "limit",
                      "value": "50"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"ts\": \"2026-10-12T08:42:30.118Z\",\n      \"call_id\": \"call_00000000001KHM9MZQ4B7E8TQM9M\",\n      \"part\": \"tools\",\n      \"level\": \"error\",\n      \"event\": \"tool_run\",\n      \"summary\": \"create_complaint · transform failed · HTTP 200 · 1.2 s · function not defined: json/0\",\n      \"name\": \"create_complaint\",\n      \"detail\": {\n        \"status\": \"transform_failed\",\n        \"http_status\": 200,\n        \"ms\": 1204,\n        \"error\": \"function not defined: json/0\",\n        \"tool_run_id\": \"trun_20c9ffcb8c6c959a4494bf66\"\n      }\n    },\n    {\n      \"ts\": \"2026-10-12T08:28:21.402Z\",\n      \"call_id\": \"call_00000000001KHKH4V1S2N6R8QKH4\",\n      \"part\": \"prompt\",\n      \"level\": \"warning\",\n      \"event\": \"tool_missing\",\n      \"summary\": \"asked for get_complaint_status · not a tool on this agent\",\n      \"name\": \"get_complaint_status\",\n      \"detail\": {\n        \"name\": \"get_complaint_status\",\n        \"turn\": 4,\n        \"advertised\": [\n          \"create_complaint\",\n          \"end_call\"\n        ]\n      }\n    }\n  ],\n  \"next_cursor\": null\n}"
            },
            {
              "name": "404 — not yours, deleted, or never existed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/logs?part=tools&limit=50",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "logs"
                  ],
                  "query": [
                    {
                      "key": "part",
                      "value": "tools"
                    },
                    {
                      "key": "level",
                      "value": "error",
                      "disabled": true
                    },
                    {
                      "key": "name",
                      "value": "create_complaint",
                      "disabled": true
                    },
                    {
                      "key": "call_id",
                      "value": "",
                      "disabled": true
                    },
                    {
                      "key": "since",
                      "value": "2026-10-11T09:00:00Z",
                      "disabled": true
                    },
                    {
                      "key": "until",
                      "value": "",
                      "disabled": true
                    },
                    {
                      "key": "limit",
                      "value": "50"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no agent agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Count agent errors and warnings",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/logs/summary",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "logs",
                "summary"
              ],
              "query": [
                {
                  "key": "since",
                  "value": "2026-10-11T09:00:00Z",
                  "disabled": true
                }
              ]
            },
            "description": "How many errors and warnings each part of the agent logged since `since` (an RFC 3339 time; the last 24 hours if you leave it out). These are the numbers on the section labels in Agent Studio. Use it to check an agent at a glance, then read the rows with `GET /v2/agents/{id}/logs`."
          },
          "response": [
            {
              "name": "200 — the last 24 hours",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/logs/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "logs",
                    "summary"
                  ],
                  "query": [
                    {
                      "key": "since",
                      "value": "2026-10-11T09:00:00Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"parts\": {\n    \"prompt\": {\n      \"errors\": 0,\n      \"warnings\": 4\n    },\n    \"tools\": {\n      \"errors\": 3,\n      \"warnings\": 0\n    },\n    \"variables\": {\n      \"errors\": 0,\n      \"warnings\": 0\n    },\n    \"results\": {\n      \"errors\": 0,\n      \"warnings\": 1\n    },\n    \"calls\": {\n      \"errors\": 0,\n      \"warnings\": 1\n    }\n  }\n}"
            },
            {
              "name": "404 — not yours, deleted, or never existed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/logs/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "logs",
                    "summary"
                  ],
                  "query": [
                    {
                      "key": "since",
                      "value": "2026-10-11T09:00:00Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no agent agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Check how well it hears",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/stt-accuracy",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "stt-accuracy"
              ]
            },
            "description": "The campaign hearing check (`GET /v2/campaigns/{id}/stt-accuracy`), summed over every campaign this agent runs: the share of caller words it heard right, day by day, and the words it keeps getting wrong. The same fields as a campaign's, except `auto_learn`, which is always false here: Keep learning is a campaign setting. Words to catch you add to the agent help all of its campaigns.\n\nIt's a machine check against our offline transcript, not a person listening, so read it as a trend."
          },
          "response": [
            {
              "name": "200 — checked on its campaigns",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/stt-accuracy",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "stt-accuracy"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"status\": \"ready\",\n  \"method\": {\n    \"reference\": \"offline\",\n    \"calls_scored\": 40,\n    \"since\": \"2026-11-05\",\n    \"daily_cap\": 20\n  },\n  \"summary\": {\n    \"first_wer\": 0.27,\n    \"latest_wer\": 0.21,\n    \"calls_scored\": 40,\n    \"ref_words\": 4800,\n    \"keyterm_recall\": null\n  },\n  \"daily\": [\n    {\n      \"date\": \"2026-11-05\",\n      \"calls\": 20,\n      \"ref_words\": 2400,\n      \"wer\": 0.27,\n      \"keyterm_recall\": null\n    },\n    {\n      \"date\": \"2026-11-06\",\n      \"calls\": 20,\n      \"ref_words\": 2400,\n      \"wer\": 0.21,\n      \"keyterm_recall\": null\n    }\n  ],\n  \"keyterm_events\": [],\n  \"misheard\": [\n    {\n      \"term\": \"मिराई मोटर्स\",\n      \"heard_as\": [\n        {\n          \"text\": \"मिराय मोटर\",\n          \"count\": 6\n        }\n      ],\n      \"calls\": 5,\n      \"count\": 6,\n      \"in_keyterms\": false,\n      \"example_call_ids\": [\n        \"call_01K2M4RB8CDEFGHJKMNPQRST\"\n      ]\n    }\n  ],\n  \"suggestions\": [\n    {\n      \"term\": \"मिराई मोटर्स\",\n      \"reason\": \"misheard in 5 of 40 calls\",\n      \"confidence\": 0.8,\n      \"calls\": 5,\n      \"heard_as\": [\n        \"मिराय मोटर\"\n      ],\n      \"spellings\": [\n        \"मिराई मोटर्स\",\n        \"Mirai Motors\"\n      ]\n    }\n  ],\n  \"auto_learn\": false\n}"
            },
            {
              "name": "404 — not yours, deleted, or never existed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/stt-accuracy",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "stt-accuracy"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no agent agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get the agent schema",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/schema",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "schema"
              ]
            },
            "description": "The agent API as an OpenAPI 3.1 document: every field, limit, default and error for agents, their tools and node flows, plus worked examples. Generate a client from it, or give it to a coding assistant. It needs no key. The example below is shortened; the real document is much longer."
          },
          "response": [
            {
              "name": "200 — the contract (shortened)",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/schema",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "schema"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": {\n    \"title\": \"Mirai agent API\",\n    \"version\": \"2026-10-07.secondary-languages\"\n  },\n  \"x-scope\": \"Agent configuration only. Other product routes are not inventoried by this document.\",\n  \"components\": {\n    \"securitySchemes\": {\n      \"bearerAuth\": {\n        \"type\": \"http\",\n        \"scheme\": \"bearer\"\n      }\n    },\n    \"schemas\": {\n      \"FlowValidation\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"ok\": {\n            \"const\": true\n          },\n          \"flow_revision\": {\n            \"type\": \"string\"\n          },\n          \"nodes\": {\n            \"type\": \"integer\"\n          },\n          \"edges\": {\n            \"type\": \"integer\"\n          }\n        }\n      }\n    }\n  },\n  \"security\": [\n    {\n      \"bearerAuth\": []\n    }\n  ],\n  \"paths\": {\n    \"/v2/agents/flow/validate\": {\n      \"post\": {\n        \"summary\": \"Validate a graph without saving it: the graph rules and the caller's tier model. Input_schema declarations are checked when the graph is saved on an agent.\",\n        \"requestBody\": {\n          \"required\": true,\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/Flow\"\n              }\n            }\n          }\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Valid.\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/FlowValidation\"\n                }\n              }\n            }\n          },\n          \"400\": {\n            \"description\": \"invalid_flow with a details array.\"\n          }\n        }\n      }\n    }\n  },\n  \"x-examples\": {\n    \"archive_agent\": {\n      \"if_revision\": 2,\n      \"archived\": true\n    },\n    \"restore_agent\": {\n      \"if_revision\": 3,\n      \"archived\": false\n    }\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete agent",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}"
              ]
            },
            "description": "Soft delete: the agent leaves the list and takes no new calls. Past calls keep their `agent_id`, and calls already in flight finish normally. Answers 204 with no body.\n\nTo pause an agent you may want back, archive it instead with `PATCH {\"archived\": true}`. The other folders use `{{agent_id}}`, so run this one last."
          },
          "response": [
            {
              "name": "204 — deleted",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            },
            {
              "name": "404 — not yours, deleted, or never existed",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no agent agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Calls",
      "description": "Place a call, follow it while it runs, then read what happened: the transcript, the recording, the post-call analysis.\n\n`POST /v2/calls` answers before the phone rings, with an id. Everything after that is about that id. Every call has a live event stream, phone calls included, so your own dashboard can show a call as it happens. Live control works on browser calls (`channel: \"web\"`) and realtime sessions only; a phone call answers it with `400 unsupported_channel`.",
      "item": [
        {
          "name": "Place a call",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Up to 255 characters. Postman generates a new one per Send."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"to\": \"{{test_number}}\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"reminder_id\": \"rem_8842\"\n  },\n  \"max_duration_secs\": 300\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Rings `to` and runs `agent_id` on the call. **This rings a real phone and uses wallet credit.** It answers **202** once the call is accepted. The phone hasn't rung yet, so poll *Get call*, take the webhooks sent to `webhook_url`, or follow it live: `events_url` is the call's live event stream (see *Stream live events*), with its own read-only token, so you can open it from a browser without your key.\n\nBefore your company goes live, every call runs and is billed at t5 (₹5 a minute, in 10-second blocks), whatever tier you send. The wallet must cover one minute before anything is dialled, or you get a 402 and nothing is charged.\n\n**Idempotency-Key** keeps a retry to one phone call. The same key within 24 hours replays the first 202 (with `Idempotent-Replay: true`) and dials nothing. Postman makes a fresh key on every Send, so each Send is a new call. In your own code, build the key from your own record, like `order-8842-reminder-1`.\n\nEverything but `agent_id` and `to` is optional:\n\n* `variables` fill the placeholders in the agent's prompt and first message (up to 32, 512 characters each). Tools read them as `vars.*`.\n* `metadata` is your own ids. They come back on the call and on every webhook, and the agent never sees them.\n* `webhook_url`, `max_duration_secs` (30–1800), `first_message`, `timing`, `recording_enabled` and `final_results` work as the docs describe.\n* `phone_number_id` calls from one of your own numbers (Phone numbers folder) instead of the default route.\n\n**A browser call instead:** see *Start a browser call*: the same request with `\"channel\": \"web\"` and no `to`. `\"channel\": \"realtime\"` opens an OpenAI Realtime-compatible session the same way. Both are billed per minute like a phone call."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const call_id = pick(\"id\");",
                  "  if (call_id != null && call_id !== '') pm.collectionVariables.set(\"call_id\", String(call_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "202 — accepted, not dialled yet",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"to\": \"{{test_number}}\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"reminder_id\": \"rem_8842\"\n  },\n  \"max_duration_secs\": 300\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"status\": \"queued\",\n  \"events_url\": \"https://sandbox.voice.miraiminds.co/v2/calls/call_01K2M4RB8CDEFGHJKMNPQRST/events?token=Qm4tW8yZ1cF5hJ9sD3gA7eU2iO6kN0qVb4nR8xK2pL6\"\n}"
            },
            {
              "name": "400 — not an E.164 number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"to\": \"{{test_number}}\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"reminder_id\": \"rem_8842\"\n  },\n  \"max_duration_secs\": 300\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"to must be an E.164 phone number, got '9876543210'\"\n  }\n}"
            },
            {
              "name": "402 — the wallet will not cover a minute",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"to\": \"{{test_number}}\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"reminder_id\": \"rem_8842\"\n  },\n  \"max_duration_secs\": 300\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance 3.20 INR is below the minimum for one minute at t5\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Start a browser call",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Up to 255 characters. Postman generates a new one per Send."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"channel\": \"web\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"session_id\": \"sess_8f2c41\",\n    \"user_id\": \"usr_1042\"\n  },\n  \"max_duration_secs\": 600\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Runs `agent_id` in your user's browser instead of on a phone line: the same request as *Place a call*, with `\"channel\": \"web\"` and no `to`. Send it from your server, where the key lives. It answers **202** with two links for this one call, which you hand to the page:\n\n* `ws_url` is the audio socket. The page opens it as a WebSocket and streams raw PCM both ways: 16-bit little-endian, mono, 48,000 Hz, 20 ms frames. It is single use; connect before `ws_url_expires_at` (5 minutes). The text message `{\"event\":\"clear\"}` means the user interrupted: drop queued agent audio.\n* `events_url` is the live event stream (Server-Sent Events): `agent.state`, `transcript.turn` and finally `call.ended`. *Stream live events* reads the same stream with your key.\n\nThe call stays `queued` until the page connects its audio, then goes `in_progress`; if nothing connects before the link expires, it ends `failed` with `ended_reason: \"no-media\"` and costs nothing. Billing starts when audio goes live, at the same per-minute rate as a phone call. Steer or end it with *Send a live control*.\n\nThe id is saved as `call_id`, so the live-control and event requests below use this call."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const call_id = pick(\"id\");",
                  "  if (call_id != null && call_id !== '') pm.collectionVariables.set(\"call_id\", String(call_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "202 — accepted, waiting for the browser",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"channel\": \"web\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"session_id\": \"sess_8f2c41\",\n    \"user_id\": \"usr_1042\"\n  },\n  \"max_duration_secs\": 600\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\n  \"status\": \"queued\",\n  \"transport\": \"web\",\n  \"ws_url\": \"wss://sandbox.voice.miraiminds.co/v2/calls/call_01K2M5W3B7D9F1H3K5M7P9R1T3/media?token=c9oQ2xK9pL4mR8tW1yZ6cF3hJ0sD5gA2eU7iO4kN9qV\",\n  \"ws_url_expires_at\": \"2026-10-09T10:05:00Z\",\n  \"events_url\": \"https://sandbox.voice.miraiminds.co/v2/calls/call_01K2M5W3B7D9F1H3K5M7P9R1T3/events?token=Vb7nQ2xK9pL4mR8tW1yZ6cF3hJ0sD5gA2eU7iO4kN9q\"\n}"
            },
            {
              "name": "400 — to sent with channel web",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"channel\": \"web\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"session_id\": \"sess_8f2c41\",\n    \"user_id\": \"usr_1042\"\n  },\n  \"max_duration_secs\": 600\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"to is not accepted for channel web: a web call connects the browser that placed it, and no number is dialled\"\n  }\n}"
            },
            {
              "name": "402 — the wallet will not cover a minute",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"agent_id\": \"{{agent_id}}\",\n  \"channel\": \"web\",\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"metadata\": {\n    \"session_id\": \"sess_8f2c41\",\n    \"user_id\": \"usr_1042\"\n  },\n  \"max_duration_secs\": 600\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance 3.20 INR is below the minimum for one minute at t5\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get call",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}"
              ]
            },
            "description": "The call record. `status` moves `queued → dialing → in_progress`, then lands on one final value: `completed`, `voicemail`, `no_answer`, `busy`, `failed`, `timeout` or `aborted`. A final status never changes. `ended_reason` says why it ended.\n\n`cost` is settled when the call ends. Only calls that connected are billed. `analysis` appears once the post-call analysis has settled (see *Get call analysis*), and a call run by a node-based agent also carries `flow`.\n\nWebhooks are the better way to follow a call. If you poll, poll every 5 seconds at most. A call id from another workspace is a 404, the same as one that never existed."
          },
          "response": [
            {
              "name": "200 — a finished call",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"object\": \"call\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"agent_revision\": 4,\n  \"to\": \"+919876543210\",\n  \"route\": \"trunk\",\n  \"direction\": \"outbound\",\n  \"channel\": \"phone\",\n  \"tier\": \"t5\",\n  \"status\": \"completed\",\n  \"ended_reason\": \"assistant-ended-call\",\n  \"created_at\": \"2026-10-09T09:15:12.408913574Z\",\n  \"started_at\": \"2026-10-09T09:15:19Z\",\n  \"ended_at\": \"2026-10-09T09:16:55Z\",\n  \"duration_secs\": 96,\n  \"cost\": {\n    \"amount_inr\": 8.33,\n    \"per_min_inr\": 5,\n    \"billing_block_secs\": 10,\n    \"voice_per_min_inr\": 5\n  },\n  \"cost_inr\": 8.33,\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"max_duration_secs\": 300,\n  \"metadata\": {\n    \"reminder_id\": \"rem_8842\"\n  },\n  \"recording_available\": true,\n  \"transcript_available\": true,\n  \"transcript_status\": \"ready\",\n  \"analysis\": {\n    \"status\": \"done\",\n    \"state\": \"completed\",\n    \"generation\": 1,\n    \"agent_revision\": 4,\n    \"completed_at\": \"2026-10-09T09:17:08Z\",\n    \"summary\": \"Rahul agreed to service his Swift on 18 October and booked the 10:30 slot. No follow-up needed.\",\n    \"success\": true,\n    \"data\": {\n      \"service_booked\": true,\n      \"preferred_date\": \"2026-10-18\",\n      \"callback_needed\": false\n    }\n  }\n}"
            },
            {
              "name": "200 — still ringing",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"object\": \"call\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"agent_revision\": 4,\n  \"to\": \"+919876543210\",\n  \"route\": \"trunk\",\n  \"direction\": \"outbound\",\n  \"channel\": \"phone\",\n  \"tier\": \"t5\",\n  \"status\": \"dialing\",\n  \"ended_reason\": null,\n  \"created_at\": \"2026-10-09T09:15:12.408913574Z\",\n  \"started_at\": null,\n  \"ended_at\": null,\n  \"duration_secs\": 0,\n  \"cost\": {\n    \"amount_inr\": 0,\n    \"per_min_inr\": 5,\n    \"billing_block_secs\": 10,\n    \"voice_per_min_inr\": 5\n  },\n  \"cost_inr\": null,\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अक्टूबर\",\n    \"customer_id\": \"cus_42\"\n  },\n  \"max_duration_secs\": 300,\n  \"metadata\": {\n    \"reminder_id\": \"rem_8842\"\n  },\n  \"recording_available\": false,\n  \"transcript_available\": false,\n  \"transcript_status\": \"pending\",\n  \"analysis\": null\n}"
            },
            {
              "name": "404 — no such call",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no call call_01K2M4RB8CDEFGHJKMNPQRST\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List calls",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "`next_cursor` from the previous page.",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "completed",
                  "disabled": true
                },
                {
                  "key": "agent_id",
                  "value": "{{agent_id}}",
                  "disabled": true
                },
                {
                  "key": "from",
                  "value": "2026-10-01T00:00:00Z",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "2026-10-31T23:59:59Z",
                  "disabled": true
                }
              ]
            },
            "description": "Your calls, newest first. `limit` is 1–100 (default 20). When `has_more` is true, send `next_cursor` back as `cursor` for the next page. Filter with `agent_id`, `status`, and `from`/`to` on `created_at` (RFC 3339, UTC).\n\nEach row carries `cost_inr` rather than the full `cost` breakdown, and a running call can still read `queued` here. *Get call* has the live status, the breakdown and the analysis. Use the list for reconciliation and reports; use webhooks to drive your app."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "`next_cursor` from the previous page.",
                      "disabled": true
                    },
                    {
                      "key": "status",
                      "value": "completed",
                      "disabled": true
                    },
                    {
                      "key": "agent_id",
                      "value": "{{agent_id}}",
                      "disabled": true
                    },
                    {
                      "key": "from",
                      "value": "2026-10-01T00:00:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-10-31T23:59:59Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n      \"object\": \"call\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"agent_revision\": 4,\n      \"to\": \"+919876543210\",\n      \"route\": \"trunk\",\n      \"direction\": \"outbound\",\n      \"channel\": \"phone\",\n      \"tier\": \"t5\",\n      \"status\": \"completed\",\n      \"ended_reason\": \"assistant-ended-call\",\n      \"created_at\": \"2026-10-09T09:15:12.408913574Z\",\n      \"started_at\": \"2026-10-09T09:15:19.120044861Z\",\n      \"ended_at\": \"2026-10-09T09:16:55.302187420Z\",\n      \"duration_secs\": 96,\n      \"billing_block_secs\": 10,\n      \"variables\": {\n        \"name\": \"राहुल\",\n        \"vehicle\": \"स्विफ्ट\",\n        \"due_date\": \"18 अक्टूबर\",\n        \"customer_id\": \"cus_42\"\n      },\n      \"max_duration_secs\": 300,\n      \"metadata\": {\n        \"reminder_id\": \"rem_8842\"\n      },\n      \"cost_inr\": 8.33,\n      \"recording_available\": true,\n      \"transcript_available\": true,\n      \"transcript_status\": \"ready\",\n      \"analysis\": null\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            },
            {
              "name": "400 — limit out of range",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "`next_cursor` from the previous page.",
                      "disabled": true
                    },
                    {
                      "key": "status",
                      "value": "completed",
                      "disabled": true
                    },
                    {
                      "key": "agent_id",
                      "value": "{{agent_id}}",
                      "disabled": true
                    },
                    {
                      "key": "from",
                      "value": "2026-10-01T00:00:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-10-31T23:59:59Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"limit must be between 1 and 100.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Count calls",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/summary",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "summary"
              ],
              "query": [
                {
                  "key": "from",
                  "value": "2026-10-01T00:00:00Z",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "2026-11-01T00:00:00Z",
                  "disabled": true
                }
              ]
            },
            "description": "How many calls your workspace has made and taken, without paging through them: the total, by channel (`phone`, `web`, `text`, `realtime`) and by direction (`outbound`, `inbound`), and their total duration in seconds. These are the figures on the console's Calls page.\n\n`from`/`to` (RFC 3339, UTC) count only calls created in that window, the same window *List calls* filters on. Every count is always present, zero included. A `503` means the totals could not be read right now: retry, and don't read it as zero calls."
          },
          "response": [
            {
              "name": "200 — this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "summary"
                  ],
                  "query": [
                    {
                      "key": "from",
                      "value": "2026-10-01T00:00:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-11-01T00:00:00Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"call_summary\",\n  \"total\": 1240,\n  \"by_channel\": {\n    \"phone\": 1096,\n    \"web\": 118,\n    \"text\": 20,\n    \"realtime\": 6\n  },\n  \"by_direction\": {\n    \"outbound\": 1012,\n    \"inbound\": 228\n  },\n  \"duration_secs\": 98412,\n  \"from\": null,\n  \"to\": null\n}"
            },
            {
              "name": "503 — totals unavailable",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "summary"
                  ],
                  "query": [
                    {
                      "key": "from",
                      "value": "2026-10-01T00:00:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-11-01T00:00:00Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"summary_unavailable\",\n    \"message\": \"could not read the call record; try again shortly\"\n  }\n}"
            }
          ]
        },
        {
          "name": "How your calls went",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/insights",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "insights"
              ],
              "query": [
                {
                  "key": "from",
                  "value": "2026-10-06T18:30:00Z",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "2026-11-05T09:12:44Z",
                  "disabled": true
                }
              ]
            },
            "description": "Every call your workspace made and took in a window, read as a whole: how many connected, how many the agent judged a success, the talk time, what the calls were charged, where they came from (campaigns, incoming calls, one-off calls from the API or the console, browser tests, text, realtime), each agent and number, a day-by-day count, how long callers waited for a reply, and an `attention` list of things that need you (an empty wallet, a number not added, an agent that could not take its calls). These are the figures on the console's Overview page.\n\n`from`/`to` (RFC 3339, UTC) bound the window; calls count by when they were created, as *List calls* filters them. Without them it is the last 30 days. The window is at most 92 days. `daily` is one row per India day (Asia/Kolkata) the window touches.\n\nEvery key is always present. A rate or a reply time is `null` when there is nothing to divide or measure, never `0`. Money is call charges only, in paise (the statement has everything else). A `503` means the figures could not be read right now: retry, and don't read it as a quiet month."
          },
          "response": [
            {
              "name": "200 — the last 30 days",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "insights"
                  ],
                  "query": [
                    {
                      "key": "from",
                      "value": "2026-10-06T18:30:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-11-05T09:12:44Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"workspace_insights\",\n  \"workspace_id\": \"ws_01K2M4N8B3C5D7F9G1H3J5K7M9\",\n  \"from\": \"2026-10-06T18:30:00Z\",\n  \"to\": \"2026-11-05T09:12:44Z\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"calls\": {\n    \"total\": 1240,\n    \"in_progress\": 2,\n    \"settled\": 1238,\n    \"connected\": 812,\n    \"not_answered\": 301,\n    \"failed\": 38,\n    \"stopped\": 23,\n    \"other\": 64,\n    \"short\": 96,\n    \"engaged\": 503,\n    \"talk_secs\": 98412,\n    \"talk_p50_secs\": 94,\n    \"connect_rate_pct\": 65.6,\n    \"failure_rate_pct\": 3.1,\n    \"short_rate_pct\": 11.8\n  },\n  \"outcomes\": {\n    \"analysed\": 790,\n    \"success\": 412,\n    \"not_success\": 318,\n    \"no_verdict\": 60,\n    \"pending\": 9,\n    \"analysis_failed\": 13,\n    \"success_rate_pct\": 56.4\n  },\n  \"money\": {\n    \"billed_paise\": 1096500,\n    \"billed_calls\": 820,\n    \"per_connected_paise\": 1350,\n    \"per_success_paise\": 2661,\n    \"per_talk_minute_paise\": 669\n  },\n  \"quality\": {\n    \"calls_measured\": 790,\n    \"v2v_turns\": 9120,\n    \"v2v_p50_ms\": 1080,\n    \"v2v_p95_ms\": 1620,\n    \"first_audio_p50_ms\": 2310\n  },\n  \"by_origin\": {\n    \"campaign\": {\n      \"calls\": 980,\n      \"connected\": 610,\n      \"failed\": 30,\n      \"stopped\": 21,\n      \"talk_secs\": 71230,\n      \"billed_paise\": 812400,\n      \"success\": 318,\n      \"not_success\": 250\n    },\n    \"inbound\": {\n      \"calls\": 160,\n      \"connected\": 142,\n      \"failed\": 4,\n      \"stopped\": 2,\n      \"talk_secs\": 19870,\n      \"billed_paise\": 201300,\n      \"success\": 70,\n      \"not_success\": 55\n    },\n    \"outbound\": {\n      \"calls\": 64,\n      \"connected\": 38,\n      \"failed\": 3,\n      \"stopped\": 0,\n      \"talk_secs\": 5210,\n      \"billed_paise\": 64600,\n      \"success\": 18,\n      \"not_success\": 10\n    },\n    \"web\": {\n      \"calls\": 30,\n      \"connected\": 18,\n      \"failed\": 1,\n      \"stopped\": 0,\n      \"talk_secs\": 1830,\n      \"billed_paise\": 15300,\n      \"success\": 5,\n      \"not_success\": 3\n    },\n    \"text\": {\n      \"calls\": 4,\n      \"connected\": 2,\n      \"failed\": 0,\n      \"stopped\": 0,\n      \"talk_secs\": 120,\n      \"billed_paise\": 900,\n      \"success\": 1,\n      \"not_success\": 0\n    },\n    \"realtime\": {\n      \"calls\": 2,\n      \"connected\": 2,\n      \"failed\": 0,\n      \"stopped\": 0,\n      \"talk_secs\": 152,\n      \"billed_paise\": 2000,\n      \"success\": 0,\n      \"not_success\": 0\n    }\n  },\n  \"by_agent\": [\n    {\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"name\": \"Service reminder\",\n      \"deleted\": false,\n      \"calls\": 1044,\n      \"connected\": 652,\n      \"failed\": 33,\n      \"stopped\": 21,\n      \"short\": 81,\n      \"talk_secs\": 76440,\n      \"billed_paise\": 877000,\n      \"success\": 336,\n      \"not_success\": 260,\n      \"success_rate_pct\": 56.4,\n      \"v2v_p50_ms\": 1060\n    },\n    {\n      \"agent_id\": \"agt_01K2M4Q2W4Y6A8C0E2G4J6L8N0\",\n      \"name\": \"Front desk\",\n      \"deleted\": false,\n      \"calls\": 196,\n      \"connected\": 160,\n      \"failed\": 5,\n      \"stopped\": 2,\n      \"short\": 15,\n      \"talk_secs\": 21972,\n      \"billed_paise\": 219500,\n      \"success\": 76,\n      \"not_success\": 58,\n      \"success_rate_pct\": 56.7,\n      \"v2v_p50_ms\": 1190\n    }\n  ],\n  \"daily\": [\n    {\n      \"day\": \"2026-11-04\",\n      \"calls\": 61,\n      \"connected\": 40,\n      \"not_answered\": 15,\n      \"failed\": 2,\n      \"stopped\": 1,\n      \"talk_secs\": 4870,\n      \"billed_paise\": 53800,\n      \"success\": 21,\n      \"v2v_p50_ms\": 1070\n    },\n    {\n      \"day\": \"2026-11-05\",\n      \"calls\": 22,\n      \"connected\": 15,\n      \"not_answered\": 5,\n      \"failed\": 1,\n      \"stopped\": 0,\n      \"talk_secs\": 1760,\n      \"billed_paise\": 19700,\n      \"success\": 7,\n      \"v2v_p50_ms\": 1100\n    }\n  ],\n  \"refused\": {\n    \"total\": 12,\n    \"by_code\": {\n      \"insufficient_balance\": 12\n    },\n    \"last_at\": \"2026-11-02T06:41:09Z\"\n  },\n  \"tools\": {\n    \"runs\": 640,\n    \"failed\": 9\n  },\n  \"numbers\": [\n    {\n      \"number_id\": \"pn_01K2M4R6T8V0X2Z4B6D8F0H2K4\",\n      \"number\": \"+918035312390\",\n      \"health_state\": \"active\",\n      \"attempts\": 812,\n      \"answers\": 529,\n      \"answer_rate_pct\": 65.1\n    }\n  ],\n  \"inbound_misses\": {\n    \"numbers\": 0,\n    \"calls\": 0,\n    \"last_at\": null\n  },\n  \"attention\": [\n    {\n      \"code\": \"wallet\",\n      \"severity\": \"act\",\n      \"count\": 35,\n      \"last_at\": \"2026-11-02T06:41:09Z\",\n      \"subject\": null\n    }\n  ]\n}"
            },
            {
              "name": "400 — a window over 92 days",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "insights"
                  ],
                  "query": [
                    {
                      "key": "from",
                      "value": "2026-10-06T18:30:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-11-05T09:12:44Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"the window is at most 92 days\"\n  }\n}"
            },
            {
              "name": "503 — figures unavailable",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "insights"
                  ],
                  "query": [
                    {
                      "key": "from",
                      "value": "2026-10-06T18:30:00Z",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-11-05T09:12:44Z",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insights_unavailable\",\n    \"message\": \"could not read the call record; try again shortly\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Stream live events",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "text/event-stream"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/events",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "events"
              ],
              "query": [
                {
                  "key": "after",
                  "value": "1791540084020-0",
                  "description": "Start after this event id.",
                  "disabled": true
                }
              ]
            },
            "description": "What's happening on a call, as it happens, over [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events). Every call has it: phone calls (outbound, campaign and inbound), browser calls and realtime sessions.\n\n**This response doesn't finish on its own.** It stays open and sends each event as it occurs: `agent.state` (listening, processing, speaking), `transcript.turn` for every completed turn, `turn.metrics` with how fast each agent reply came (`latency_ms` from the caller stopping to the reply's audio, and each stage's first-byte time), `tool.started` and `tool.completed` for each tool the agent runs during the call (names and timings, never arguments or results), `flow.node.entered` and `flow.variables.extracted` for a node-based agent, `language.changed` when the call switches language because the caller asked for another one or spoke it (and `language.not_enabled` when they asked for one the agent does not have), and finally `call.ended`, after which the stream closes. Postman lists the events as they arrive; press Cancel to stop early.\n\nEvery event has an `id`. To resume after a drop, send it back as `after` (or as the `Last-Event-ID` header) and the stream carries on after that event. Events are kept for an hour after the call ends, so opening a finished call replays it and closes. A reader already past `call.ended` gets `204`.\n\nA phone call's stream opens when it is placed and stays quiet while it rings; the first event arrives when the call is answered. A call that is never answered (busy, no answer) sends only `call.ended`, with the call's `status`.\n\nYour API key works here, from your backend, for any call in your workspace. A browser should open the `events_url` that creating the call returned, which carries its own token, so your key never reaches the page. A campaign or inbound call has no create response, so read its stream with your key."
          },
          "response": [
            {
              "name": "200 — the stream, through to call.ended",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "text/event-stream"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/events",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "events"
                  ],
                  "query": [
                    {
                      "key": "after",
                      "value": "1791540084020-0",
                      "description": "Start after this event id.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "text",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/event-stream"
                }
              ],
              "cookie": [],
              "body": "retry: 2000\n\nid: 1791540082114-0\nevent: agent.state\ndata: {\"v\":1,\"seq\":1,\"type\":\"agent.state\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:01:22.114Z\",\"data\":{\"state\":\"speaking\"}}\n\nid: 1791540084020-0\nevent: transcript.turn\ndata: {\"v\":1,\"seq\":2,\"type\":\"transcript.turn\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:01:24.020Z\",\"data\":{\"role\":\"assistant\",\"text\":\"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\"turn\":1,\"interrupted\":false}}\n\nid: 1791540089380-0\nevent: agent.state\ndata: {\"v\":1,\"seq\":3,\"type\":\"agent.state\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:01:29.380Z\",\"data\":{\"state\":\"listening\"}}\n\nid: 1791540091902-0\nevent: transcript.turn\ndata: {\"v\":1,\"seq\":4,\"type\":\"transcript.turn\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:01:31.902Z\",\"data\":{\"role\":\"user\",\"text\":\"हाँ बोलिए\",\"turn\":2,\"interrupted\":false}}\n\nid: 1791540092794-0\nevent: agent.state\ndata: {\"v\":1,\"seq\":5,\"type\":\"agent.state\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:01:32.794Z\",\"data\":{\"state\":\"speaking\"}}\n\nid: 1791540092795-0\nevent: turn.metrics\ndata: {\"v\":1,\"seq\":6,\"type\":\"turn.metrics\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:01:32.794Z\",\"data\":{\"reply\":2,\"latency_ms\":892.4,\"stt_ms\":141.0,\"llm_ms\":402.6,\"tts_ms\":188.3}}\n\n: ping\n\nid: 1791540291412-0\nevent: call.ended\ndata: {\"v\":1,\"seq\":31,\"type\":\"call.ended\",\"call_id\":\"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\"at\":\"2026-10-09T10:04:51.412Z\",\"data\":{\"reason\":\"api-ended-call\",\"status\":\"completed\"}}\n\n"
            },
            {
              "name": "200 — a phone call nobody answered",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "text/event-stream"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/events",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "events"
                  ],
                  "query": [
                    {
                      "key": "after",
                      "value": "1791540084020-0",
                      "description": "Start after this event id.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "text",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/event-stream"
                }
              ],
              "cookie": [],
              "body": "retry: 2000\n\nid: 1791540106233-0\nevent: call.ended\ndata: {\"v\":1,\"seq\":1,\"type\":\"call.ended\",\"call_id\":\"call_01K2M4RB8CDEFGHJKMNPQRST\",\"at\":\"2026-10-09T10:01:46.233Z\",\"data\":{\"reason\":\"customer-did-not-answer\",\"status\":\"no_answer\",\"synthesized\":true}}\n\n"
            },
            {
              "name": "401 — the events_url token expired or is for another call",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Accept",
                    "value": "text/event-stream"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/events",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "events"
                  ],
                  "query": [
                    {
                      "key": "after",
                      "value": "1791540084020-0",
                      "description": "Start after this event id.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_token\",\n    \"message\": \"the events token is missing, expired or not for this call\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Send a live control",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}",
                "description": "Up to 255 characters. Postman generates a new one per Send."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/control",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "control"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"instruction\",\n  \"text\": \"The customer is in a hurry. Stop asking new questions, confirm the slot and wrap up.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Steers a browser or realtime call while it is in progress. Send it from your backend.\n\n* `{\"type\": \"instruction\", \"text\": …}` (1–1,000 characters) gives the agent a direction it follows from its next reply for the rest of the call. It isn't read aloud.\n* `{\"type\": \"close\", \"message\": …}` speaks `message` (optional, up to 500 characters) as a goodbye and ends the call: `completed`, `ended_reason: api-ended-call`, billed like any completed call. Without `message` the agent uses its own closing line.\n\nIt answers **200** when the live call confirmed it within 3 seconds (`applied`, or `rejected` with a `reason`), and **202** with `status: pending` otherwise. Check a pending one with *Get a live control*. The call must be live: still `queued` (the page hasn't connected) or already ended is a `409 call_not_active`.\n\nSend an Idempotency-Key. A repeat with the same key returns the same control and is never delivered twice, so a retry can't make the agent say goodbye twice."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const control_id = pick(\"id\");",
                  "  if (control_id != null && control_id !== '') pm.collectionVariables.set(\"control_id\", String(control_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — applied by the live call",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/control",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "control"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"type\": \"instruction\",\n  \"text\": \"The customer is in a hurry. Stop asking new questions, confirm the slot and wrap up.\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ctl_01K2M5X8C2E4G6J8M0P2R4T6V8\",\n  \"object\": \"call_control\",\n  \"call_id\": \"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\n  \"type\": \"instruction\",\n  \"status\": \"applied\",\n  \"created_at\": \"2026-10-09T10:03:10.120417Z\",\n  \"applied_at\": \"2026-10-09T10:03:10.410233Z\"\n}"
            },
            {
              "name": "400 — a phone call can't be steered",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/control",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "control"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"type\": \"instruction\",\n  \"text\": \"The customer is in a hurry. Stop asking new questions, confirm the slot and wrap up.\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"unsupported_channel\",\n    \"message\": \"live control is available for web and realtime calls only\"\n  }\n}"
            },
            {
              "name": "409 — the browser hasn't connected yet",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}",
                    "description": "Up to 255 characters. Postman generates a new one per Send."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/control",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "control"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"type\": \"instruction\",\n  \"text\": \"The customer is in a hurry. Stop asking new questions, confirm the slot and wrap up.\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"call_not_active\",\n    \"message\": \"call call_01K2M5W3B7D9F1H3K5M7P9R1T3 is queued; live control opens once the browser has connected\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get a live control",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/control/{{control_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "control",
                "{{control_id}}"
              ]
            },
            "description": "Where a control stands now. `pending` means sent but not yet confirmed by the live call; `applied` sets `applied_at`; `rejected` gives a `reason`, such as `call_ending` or `already_closed` (a `close` was already applied); `failed` means it couldn't be applied. Controls can be read for an hour after the call ends."
          },
          "response": [
            {
              "name": "200 — applied",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/control/{{control_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "control",
                    "{{control_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ctl_01K2M5X8C2E4G6J8M0P2R4T6V8\",\n  \"object\": \"call_control\",\n  \"call_id\": \"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\n  \"type\": \"instruction\",\n  \"status\": \"applied\",\n  \"created_at\": \"2026-10-09T10:03:10.120417Z\",\n  \"applied_at\": \"2026-10-09T10:03:10.410233Z\"\n}"
            },
            {
              "name": "200 — rejected: the call was already closing",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/control/{{control_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "control",
                    "{{control_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ctl_01K2M5X8C2E4G6J8M0P2R4T6V8\",\n  \"object\": \"call_control\",\n  \"call_id\": \"call_01K2M5W3B7D9F1H3K5M7P9R1T3\",\n  \"type\": \"close\",\n  \"status\": \"rejected\",\n  \"created_at\": \"2026-10-09T10:03:10.120417Z\",\n  \"reason\": \"already_closed\"\n}"
            },
            {
              "name": "404 — no such control on this call",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/control/{{control_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "control",
                    "{{control_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no control ctl_01K2M5X8C2E4G6J8M0P2R4T6V8 on call call_01K2M5W3B7D9F1H3K5M7P9R1T3\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Abort call",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/abort",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "abort"
              ]
            },
            "description": "Stops a call that hasn't ended, whether it is queued, ringing or mid-conversation. **If someone has picked up, they are cut off with no goodbye.** On a browser call, *Send a live control* with `close` ends it gracefully instead.\n\nIt answers 202 straight away. The call then settles as `aborted` with `ended_reason: aborted-by-api`, and `call.aborted` fires. An aborted call is billed for the time it was connected, like any other call; one aborted while queued or ringing costs nothing. A call that has already ended is a 409: the ending it has is the real one."
          },
          "response": [
            {
              "name": "202 — stopping",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/abort",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "abort"
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"status\": \"aborting\"\n}"
            },
            {
              "name": "409 — it already ended",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/abort",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "abort"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"Call is already completed.\"\n  }\n}"
            },
            {
              "name": "404 — no such call",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/abort",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "abort"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"No such call.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get transcript",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/transcript",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "transcript"
              ]
            },
            "description": "What was said, as turns, once the call has ended. `role` is `assistant` or `user`, and text comes as it was spoken, never translated. `start_ms`/`end_ms` are milliseconds from the start of the recording, so a turn lines up with the audio. The last turn of a call that was cut off may have no `end_ms`.\n\nA 404 means either the call is still running or nobody spoke. The call's `transcript_status` (`pending`, `ready`, `empty` or `failed`) tells you which."
          },
          "response": [
            {
              "name": "200 — the turns",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/transcript",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "transcript"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"turns\": [\n    {\n      \"role\": \"assistant\",\n      \"text\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n      \"start_ms\": 320,\n      \"end_ms\": 4180\n    },\n    {\n      \"role\": \"user\",\n      \"text\": \"हाँ बोलिए\",\n      \"start_ms\": 4620,\n      \"end_ms\": 5510\n    },\n    {\n      \"role\": \"assistant\",\n      \"text\": \"राहुल जी, आपकी स्विफ्ट की सर्विस 18 अक्टूबर को ड्यू है. स्लॉट बुक कर दूं?\",\n      \"start_ms\": 5880,\n      \"end_ms\": 10240\n    }\n  ]\n}"
            },
            {
              "name": "404 — nothing said yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/transcript",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "transcript"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"transcript not available (call still in progress or produced no speech)\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get recording",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/recording",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "recording"
              ]
            },
            "description": "A **302** to a signed link for the call's audio (WAV). The link expires in 15 minutes and works for anyone who holds it, so fetch the audio now and keep the call id, not the link. Ask again whenever you need a fresh one.\n\nPostman follows the redirect and downloads the file. Turn off *Settings → Automatically follow redirects* to see the `Location` header instead.\n\n404 while the call is running, for a call with no audio, and for every call placed with `recording_enabled: false`. `recording_available` on the call tells you whether to ask. Recordings are kept for 90 days."
          },
          "response": [
            {
              "name": "302 — follow the Location header",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/recording",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "recording"
                  ]
                }
              },
              "status": "Found",
              "code": 302,
              "_postman_previewlanguage": "text",
              "header": [
                {
                  "key": "Location",
                  "value": "https://storage.miraiminds.co/voice-agents/production/call_records/call_01K2M4RB8CDEFGHJKMNPQRST/call.wav?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&X-Amz-Signature=…"
                }
              ],
              "cookie": [],
              "body": ""
            },
            {
              "name": "404 — no audio for this call",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/recording",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "recording"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"recording not available (call still in progress, or it produced no audio)\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get call analysis",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "analysis"
              ]
            },
            "description": "The post-call analysis on its own, apart from the call's status: a call can be `completed` while its analysis is still `processing`.\n\n`analysis.state` is `waiting_for_call`, `pending`, `processing`, `completed`, `failed` or `skipped` (analysis is off for the agent, or the call never connected). `summary`, `success` and `data` (shaped by the agent's `analysis.output_schema`) arrive with `completed`. `generation` counts the attempts; send it back as `if_generation` to retry. The examples are for an agent with `analysis.enabled: true` and an `output_schema`; the Agents folder's agent has analysis off, so its calls read `skipped`.\n\n`delivery` is the webhook that carries the result to the call's `webhook_url` (`call.analysis.completed`, `.failed` or `.skipped`): `not_requested` when the call has no webhook, `delivered` once your endpoint took it, `failed` once every automatic retry was used up."
          },
          "response": [
            {
              "name": "200 — completed and delivered",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"analysis\": {\n    \"state\": \"completed\",\n    \"generation\": 1,\n    \"agent_revision\": 4,\n    \"summary\": \"Rahul agreed to service his Swift on 18 October and booked the 10:30 slot. No follow-up needed.\",\n    \"success\": true,\n    \"data\": {\n      \"service_booked\": true,\n      \"preferred_date\": \"2026-10-18\",\n      \"callback_needed\": false\n    },\n    \"completed_at\": \"2026-10-09T09:17:08Z\"\n  },\n  \"delivery\": {\n    \"state\": \"delivered\",\n    \"event_id\": \"evt_01K2M4S6Q8T0W2Y4A6C8E0G2J4\",\n    \"attempts\": 1\n  }\n}"
            },
            {
              "name": "200 — the call is still running",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"analysis\": {\n    \"state\": \"waiting_for_call\",\n    \"generation\": 1,\n    \"agent_revision\": 4,\n    \"success\": null\n  },\n  \"delivery\": {\n    \"state\": \"not_ready\",\n    \"attempts\": 0\n  }\n}"
            },
            {
              "name": "404 — no such call",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"call not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Retry call analysis",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/retry",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "analysis",
                "retry"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_generation\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Runs a **failed** analysis again, with the agent revision the call ran on, as the next `generation`. It can use model credit. Only a failed analysis whose webhook delivery has settled can be retried.\n\n`if_generation` must be the `generation` you just read from *Get call analysis*. If it has moved on, you get a 409 and nothing runs, so two retries can't race. It answers 202; read *Get call analysis* again to see the result."
          },
          "response": [
            {
              "name": "202 — running again as generation 2",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_generation\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"analysis\": {\n    \"state\": \"pending\",\n    \"generation\": 2,\n    \"agent_revision\": 4,\n    \"success\": null\n  },\n  \"delivery\": {\n    \"state\": \"not_ready\",\n    \"attempts\": 0\n  }\n}"
            },
            {
              "name": "409 — it didn't fail",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_generation\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"only failed analysis with settled delivery can be retried\"\n  }\n}"
            },
            {
              "name": "409 — someone retried first",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_generation\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"analysis generation changed; read it and retry\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Resend analysis webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/delivery/retry",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "analysis",
                "delivery",
                "retry"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_generation\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sends the analysis webhook again after every automatic retry failed (`delivery.state: failed`), for example once your endpoint is back up. **This calls your webhook endpoint.** It is the same event with the same `event_id`, so your dedupe still works, and the analysis itself is not run again.\n\n`if_generation` is the current `generation` from *Get call analysis*."
          },
          "response": [
            {
              "name": "202 — queued to send again",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/delivery/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis",
                    "delivery",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_generation\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"analysis\": {\n    \"state\": \"completed\",\n    \"generation\": 1,\n    \"agent_revision\": 4,\n    \"summary\": \"Rahul agreed to service his Swift on 18 October and booked the 10:30 slot. No follow-up needed.\",\n    \"success\": true,\n    \"data\": {\n      \"service_booked\": true,\n      \"preferred_date\": \"2026-10-18\",\n      \"callback_needed\": false\n    },\n    \"completed_at\": \"2026-10-09T09:17:08Z\"\n  },\n  \"delivery\": {\n    \"state\": \"pending\",\n    \"event_id\": \"evt_01K2M4S6Q8T0W2Y4A6C8E0G2J4\",\n    \"attempts\": 6,\n    \"last_error\": \"Delivery retries exhausted; retry delivery to resend the same event.\"\n  }\n}"
            },
            {
              "name": "409 — automatic retries are still going",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/analysis/delivery/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "analysis",
                    "delivery",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_generation\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"delivery can be retried after automatic retries are exhausted\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Rerun post-call tools",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/post_call/rerun",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "post_call",
                "rerun"
              ]
            },
            "description": "Runs the call's post-call tools again, with the analysis it has now, and sends a fresh `call.processed` with the next `version`. The earlier event is never rewritten. **This calls your post-call endpoints again**, so make them safe to repeat: a rerun's requests carry a new `X-Mirai-Tool-Run-Id` you can dedupe on.\n\nIt reruns tools, not the analysis; use *Retry call analysis* for that. 409 while the call is still running, while its first post-call pass hasn't finished, or while another rerun is going. No body."
          },
          "response": [
            {
              "name": "202 — running as version 2",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/post_call/rerun",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "post_call",
                    "rerun"
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n  \"status\": \"processing\",\n  \"version\": 2\n}"
            },
            {
              "name": "409 — a rerun is already going",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/post_call/rerun",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "post_call",
                    "rerun"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"rerun_in_flight\",\n    \"message\": \"post-call processing for call_01K2M4RB8CDEFGHJKMNPQRST is already running\"\n  }\n}"
            },
            {
              "name": "409 — the call hasn't finished",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/post_call/rerun",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "post_call",
                    "rerun"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"call_in_progress\",\n    \"message\": \"call call_01K2M4RB8CDEFGHJKMNPQRST has not finished; post-call processing runs when it does\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Flows",
      "description": "A node-based agent runs the call as a graph of steps. Each node has its own instructions, and the agent moves to the next node when a transition's condition is met, so a call with branches (wrong person, not now, reschedule) stays easy to follow and to change.\n\nThe usual path: draft a graph from a brief or from recordings of your real calls, check it, test it with simulated calls, then save it on an agent. Drafting, transcribing and testing use AI models and charge your wallet; checking, saving and reading are free.\n\nFull guide: https://docs.miraiminds.co/v2/node-agents",
      "item": [
        {
          "name": "Transcribe a call recording",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/flow/transcribe",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "flow",
                "transcribe"
              ]
            },
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": [],
                  "description": "The call recording."
                },
                {
                  "key": "language",
                  "type": "text",
                  "value": "hi",
                  "description": "Optional hint, up to 32 characters: hi, en, Hinglish…"
                }
              ]
            },
            "description": "Turns one call recording into a transcript with one `AGENT:` or `CALLER:` turn per line, personal details replaced by placeholders such as `[NAME]` and `[PHONE]`. Send 2–10 of these as `examples` to Generate a flow to draft a flow from calls that went well.\n\nPick a file for `file` before you send: at most 25 MB and 15 minutes, in any common audio format (mp3, wav, m4a, ogg, webm, flac, aac, amr). Neither the audio nor the transcript is kept, so save the transcript if you want it again.\n\nThis charges your wallet, about ₹1 per minute of audio, including for a recording with no conversation in it (422). 60 per workspace per hour."
          },
          "response": [
            {
              "name": "200 — the transcript",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/transcribe",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "transcribe"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The call recording."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi",
                      "description": "Optional hint, up to 32 characters: hi, en, Hinglish…"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"flow_transcript\",\n  \"id\": \"ftr_01KZR33830ZA6MSPP4EF4FZMRW\",\n  \"transcript\": \"AGENT: नमस्ते, मैं [NAME] बोल रहा हूं, मिराई मोटर्स से. क्या मेरी बात [NAME] जी से हो रही है?\\nCALLER: हां जी, बोलिए.\\nAGENT: आपकी गाड़ी की service अगले हफ़्ते due है. किस दिन workshop आ पाएंगे?\\nCALLER: शनिवार को सुबह आ जाऊंगा.\\nAGENT: ठीक है, शनिवार सुबह. धन्यवाद जी.\",\n  \"duration_secs\": 48.6,\n  \"model\": \"gemini-3.8-flash\",\n  \"usage\": {\n    \"prompt_tokens\": 1390,\n    \"completion_tokens\": 1120\n  },\n  \"cost\": {\n    \"amount_inr\": 0.94\n  }\n}"
            },
            {
              "name": "422 — no conversation in the recording (charged)",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/transcribe",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "transcribe"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The call recording."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi",
                      "description": "Optional hint, up to 32 characters: hi, en, Hinglish…"
                    }
                  ]
                }
              },
              "status": "Unprocessable Entity",
              "code": 422,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"cost\": {\n    \"amount_inr\": 0.21\n  },\n  \"duration_secs\": 12.4,\n  \"error\": {\n    \"code\": \"transcription_failed\",\n    \"message\": \"no conversation could be transcribed from this recording; check that it is a phone call with speech\"\n  },\n  \"id\": \"ftr_01KZR34N2HV6QXKD0WJ8S3TB9E\",\n  \"model\": \"gemini-3.8-flash\",\n  \"usage\": {\n    \"prompt_tokens\": 410,\n    \"completion_tokens\": 96\n  }\n}"
            },
            {
              "name": "400 — no file chosen",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/transcribe",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "transcribe"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The call recording."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi",
                      "description": "Optional hint, up to 32 characters: hi, en, Hinglish…"
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"file is required: the call recording, at most 25 MB and 15 minutes\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Generate a flow",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/flow/generate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "flow",
                "generate"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Drafts a graph from a plain-language `brief` (up to 20,000 characters), from `examples` (2–10 `{\"transcript\": …}` objects, as Transcribe returns them), or both. Send an existing graph as `flow` to revise it instead. Nothing is saved: you get the graph, the call `variables` it reads, and a matching `input_schema` to save with it.\n\n`model` is `gemini-3.8-flash` (the default), `claude-opus-5.5` or `gpt-6-sol`. A draft takes 15–60 seconds, longer with examples.\n\nThis charges your wallet at the model's cost plus 20%, including a draft that stays invalid after three attempts (422). 30 drafts per workspace per hour."
          },
          "response": [
            {
              "name": "200 — a draft (not saved)",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/generate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "generate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"fgen_01KZR3B41GT17DYMGFV465740B\",\n  \"object\": \"flow_draft\",\n  \"model\": \"gemini-3.8-flash\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"is_start\": true,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"is_start\": false,\n          \"allow_interrupt\": false,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book the service now.\"\n        }\n      }\n    ]\n  },\n  \"variables\": [\n    {\n      \"name\": \"name\",\n      \"type\": \"string\",\n      \"description\": \"The customer's name, used to confirm who answered.\"\n    },\n    {\n      \"name\": \"vehicle\",\n      \"type\": \"string\",\n      \"description\": \"The customer's car model.\"\n    },\n    {\n      \"name\": \"due_date\",\n      \"type\": \"string\",\n      \"description\": \"The date the car's service is due.\"\n    }\n  ],\n  \"input_schema\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"due_date\": {\n        \"type\": \"string\",\n        \"description\": \"The date the car's service is due.\"\n      },\n      \"name\": {\n        \"type\": \"string\",\n        \"description\": \"The customer's name, used to confirm who answered.\"\n      },\n      \"vehicle\": {\n        \"type\": \"string\",\n        \"description\": \"The customer's car model.\"\n      }\n    },\n    \"required\": [\n      \"name\",\n      \"vehicle\",\n      \"due_date\"\n    ]\n  },\n  \"flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"rounds\": 1,\n  \"usage\": {\n    \"prompt_tokens\": 3120,\n    \"completion_tokens\": 2480\n  },\n  \"cost\": {\n    \"amount_inr\": 2.41\n  }\n}"
            },
            {
              "name": "422 — still invalid after three attempts (charged)",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/generate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "generate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Unprocessable Entity",
              "code": 422,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"cost\": {\n    \"amount_inr\": 6.12\n  },\n  \"details\": [\n    {\n      \"path\": \"flow.nodes[2]\",\n      \"message\": \"node \\\"offer_slot\\\" has no path to an endCall node\"\n    }\n  ],\n  \"error\": \"flow_generation_failed\",\n  \"id\": \"fgen_01KZR3B50RW32C2SGTEF376YT8\",\n  \"model\": \"gemini-3.8-flash\",\n  \"usage\": {\n    \"prompt_tokens\": 9840,\n    \"completion_tokens\": 7310\n  }\n}"
            },
            {
              "name": "402 — empty wallet (not charged)",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/generate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "generate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance 0.00 INR is empty; generating a flow needs a positive balance\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Validate a flow",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/flow/validate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "flow",
                "validate"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book the service now.\"\n      }\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Checks a graph against every rule without saving it: node and transition counts, ids and labels, that every node can be reached and can reach an end, and that your tier's model can run flows. Free, and it calls no one. The body is the graph itself.\n\nEvery problem comes back at once, each with the path to the field. Whether the graph's variables and node tools exist on a particular agent is checked when you save it on that agent."
          },
          "response": [
            {
              "name": "200 — valid",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/validate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "validate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book the service now.\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"edges\": 4,\n  \"flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"nodes\": 5,\n  \"ok\": true\n}"
            },
            {
              "name": "400 — every problem, with its path",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/validate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "validate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book the service now.\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"details\": [\n    {\n      \"path\": \"flow.edges[2].data.label\",\n      \"message\": \"must be a function name: a letter or underscore, then letters, digits or underscores (at most 64)\"\n    },\n    {\n      \"path\": \"flow.edges[3].data.condition\",\n      \"message\": \"is required: describe when the model should take this transition\"\n    }\n  ],\n  \"error\": \"invalid_flow\"\n}"
            }
          ]
        },
        {
          "name": "Test and fix a flow",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/flow/refine",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "flow",
                "refine"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\",\n  \"simulate\": 1,\n  \"rounds\": 1,\n  \"verify\": true,\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  },\n  \"max_duration_secs\": 300,\n  \"agent_id\": \"{{agent_id}}\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"allow_interrupt\": false\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book the service now.\"\n        }\n      }\n    ]\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Tests a graph with simulated calls, reviews what happened, fixes what the review found and tests the fix. Nothing is saved. It answers 202 straight away with a job that usually finishes in 2–6 minutes: poll Get a flow test.\n\nWhat to test with: `simulate` invented callers written from your `brief` (2 by default), `examples` (your real calls, each caller replayed against the graph), `calls` (transcripts of test calls you made), or a mix. `rounds` is the most revisions to make (1–3), and `verify` tests each revision again. `variables` are test values for the call variables. `agent_id` links the job to an agent so you can find it later.\n\nSimulated calls are text only: no phone rings and no tool runs. This charges your wallet once, when the job ends, for every model call it made. 10 per workspace per hour."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const refine_id = pick(\"id\");",
                  "  if (refine_id != null && refine_id !== '') pm.collectionVariables.set(\"refine_id\", String(refine_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "202 — started",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\",\n  \"simulate\": 1,\n  \"rounds\": 1,\n  \"verify\": true,\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  },\n  \"max_duration_secs\": 300,\n  \"agent_id\": \"{{agent_id}}\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"allow_interrupt\": false\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book the service now.\"\n        }\n      }\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Location",
                  "value": "/v2/agents/flow/refine/frf_01KZR3Q5S89NTXQ40V3KYN4JMA"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"frf_01KZR3Q5S89NTXQ40V3KYN4JMA\",\n  \"object\": \"flow_refinement\",\n  \"status\": \"running\",\n  \"stage\": \"writing_scenarios\",\n  \"progress\": {\n    \"round\": 1,\n    \"rounds\": 2,\n    \"tests_done\": 0,\n    \"tests_total\": 1\n  },\n  \"model\": \"gemini-3.8-flash\",\n  \"simulation_model\": \"voice-agent\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"input_flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"created_at\": \"2026-08-11T09:51:05Z\",\n  \"updated_at\": \"2026-08-11T09:51:05Z\",\n  \"finished_at\": null,\n  \"examples\": [],\n  \"calls\": [],\n  \"rounds\": [],\n  \"found\": [],\n  \"remaining\": [],\n  \"usage\": {\n    \"prompt_tokens\": 0,\n    \"completion_tokens\": 0\n  },\n  \"cost\": {\n    \"amount_inr\": 0.0\n  }\n}"
            },
            {
              "name": "400 — nothing to test",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\",\n  \"simulate\": 1,\n  \"rounds\": 1,\n  \"verify\": true,\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  },\n  \"max_duration_secs\": 300,\n  \"agent_id\": \"{{agent_id}}\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"allow_interrupt\": false\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book the service now.\"\n        }\n      }\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"nothing to test: give calls (1–5 transcripts of test calls you made), simulate (1–5 simulated calls), or both\"\n  }\n}"
            },
            {
              "name": "402 — empty wallet",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"brief\": \"Call Mirai Motors customers whose car is due for service and book a workshop visit. Speak everyday Hindi. First confirm you are speaking to the customer by name; if it is someone else, apologise and end the call without mentioning the car. Then say which car is due for service and on what date, and ask which day they can bring it in. Read the day back and end the call. If they don't want to book now, thank them and end. Record the day they choose.\",\n  \"language\": \"hi\",\n  \"model\": \"gemini-3.8-flash\",\n  \"simulate\": 1,\n  \"rounds\": 1,\n  \"verify\": true,\n  \"variables\": {\n    \"name\": \"राहुल\",\n    \"vehicle\": \"स्विफ्ट\",\n    \"due_date\": \"18 अगस्त\"\n  },\n  \"max_duration_secs\": 300,\n  \"agent_id\": \"{{agent_id}}\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they do not want to book now, call not_now.\",\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"allow_interrupt\": false\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book the service now.\"\n        }\n      }\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance 0.00 INR is empty; testing a flow needs a positive balance\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get a flow test",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "flow",
                "refine",
                "{{refine_id}}"
              ]
            },
            "description": "The test job as it stands. While `status` is `running`, `stage` and `progress` say where it is, and `usage` and `cost` are the totals so far.\n\nOnce `succeeded`, it carries the final `flow` (the graph you sent when nothing needed changing; see `changed`), its `variables` and `input_schema`, every round's test calls and findings, and what was `found` at first and what is still `remaining`. Save the flow with Save a flow on an agent. A job that fails says why in `error`. Jobs are kept for 24 hours."
          },
          "response": [
            {
              "name": "200 — succeeded: tested, fixed and tested again",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine",
                    "{{refine_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"frf_01KZR3Q5S89NTXQ40V3KYN4JMA\",\n  \"object\": \"flow_refinement\",\n  \"status\": \"succeeded\",\n  \"stage\": \"done\",\n  \"progress\": {\n    \"round\": 2,\n    \"rounds\": 2,\n    \"tests_done\": 1,\n    \"tests_total\": 1\n  },\n  \"model\": \"gemini-3.8-flash\",\n  \"simulation_model\": \"voice-agent\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"input_flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"created_at\": \"2026-08-11T09:51:05Z\",\n  \"updated_at\": \"2026-08-11T09:54:41Z\",\n  \"finished_at\": \"2026-08-11T09:54:41Z\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"is_start\": true,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            },\n            {\n              \"name\": \"callback_time\",\n              \"type\": \"string\",\n              \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"is_start\": false,\n          \"allow_interrupt\": false,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n        }\n      }\n    ]\n  },\n  \"variables\": [\n    {\n      \"name\": \"name\",\n      \"type\": \"string\",\n      \"description\": \"The customer's name, used to confirm who answered.\"\n    },\n    {\n      \"name\": \"vehicle\",\n      \"type\": \"string\",\n      \"description\": \"The customer's car model.\"\n    },\n    {\n      \"name\": \"due_date\",\n      \"type\": \"string\",\n      \"description\": \"The date the car's service is due.\"\n    }\n  ],\n  \"input_schema\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"due_date\": {\n        \"type\": \"string\",\n        \"description\": \"The date the car's service is due.\"\n      },\n      \"name\": {\n        \"type\": \"string\",\n        \"description\": \"The customer's name, used to confirm who answered.\"\n      },\n      \"vehicle\": {\n        \"type\": \"string\",\n        \"description\": \"The customer's car model.\"\n      }\n    },\n    \"required\": [\n      \"name\",\n      \"vehicle\",\n      \"due_date\"\n    ]\n  },\n  \"flow_revision\": \"7ad7828b147804858dad\",\n  \"changed\": true,\n  \"examples\": [],\n  \"calls\": [],\n  \"rounds\": [\n    {\n      \"flow_revision\": \"2c0eccdffdf0edca4e0a\",\n      \"tests\": [\n        {\n          \"kind\": \"simulated\",\n          \"name\": \"Simulated call 1: Busy at work\",\n          \"source\": {\n            \"kind\": \"invented\",\n            \"index\": 0\n          },\n          \"scenario\": {\n            \"name\": \"Busy at work\",\n            \"persona\": \"Rahul, 34, drives a Swift and picks up on his way into a meeting.\",\n            \"goal\": \"Does not want to talk now, but would book the service later.\",\n            \"behaviour\": \"Short, slightly impatient answers. Says he is busy as soon as the service comes up.\",\n            \"language\": \"Hindi\",\n            \"variables\": {\n              \"due_date\": \"18 अगस्त\",\n              \"name\": \"राहुल\",\n              \"vehicle\": \"स्विफ्ट\"\n            }\n          },\n          \"transcript\": [\n            {\n              \"role\": \"agent\",\n              \"text\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात राहुल जी से हो रही है?\",\n              \"node_id\": \"identity\",\n              \"node_name\": \"Confirm the customer\"\n            },\n            {\n              \"role\": \"caller\",\n              \"text\": \"हां बोलिए, जल्दी बताइए.\"\n            },\n            {\n              \"role\": \"transition\",\n              \"text\": \"confirmed_identity\",\n              \"node_id\": \"offer_slot\",\n              \"node_name\": \"Book the service\"\n            },\n            {\n              \"role\": \"agent\",\n              \"text\": \"राहुल जी, आपकी स्विफ्ट की service 18 अगस्त को due है. आप किस दिन workshop आ पाएंगे?\",\n              \"node_id\": \"offer_slot\",\n              \"node_name\": \"Book the service\"\n            },\n            {\n              \"role\": \"caller\",\n              \"text\": \"अभी meeting में जा रहा हूं, अभी नहीं.\"\n            },\n            {\n              \"role\": \"transition\",\n              \"text\": \"not_now\",\n              \"node_id\": \"goodbye\",\n              \"node_name\": \"Close\"\n            },\n            {\n              \"role\": \"agent\",\n              \"text\": \"ठीक है राहुल जी, अभी service बुक नहीं करते. धन्यवाद, आपका दिन शुभ हो.\",\n              \"node_id\": \"goodbye\",\n              \"node_name\": \"Close\"\n            }\n          ],\n          \"nodes_visited\": [\n            \"Confirm the customer\",\n            \"Book the service\",\n            \"Close\"\n          ],\n          \"model\": \"voice-agent\",\n          \"ended\": \"end_node\",\n          \"estimated_secs\": 24\n        }\n      ],\n      \"findings\": [\n        {\n          \"severity\": \"medium\",\n          \"title\": \"A busy caller is let go without a callback time\",\n          \"evidence\": \"Simulated call 1: the caller said \\\"अभी meeting में जा रहा हूं, अभी नहीं.\\\" and the agent called not_now at once and closed, so nobody knows when to call back.\",\n          \"fix\": \"In offer_slot, when the caller is busy, ask once when to call back before not_now, and extract the answer as callback_time.\",\n          \"nodes\": [\n            \"offer_slot\"\n          ]\n        }\n      ],\n      \"verdict\": \"needs_changes\",\n      \"revised\": true,\n      \"revision_issues\": []\n    },\n    {\n      \"flow_revision\": \"7ad7828b147804858dad\",\n      \"tests\": [\n        {\n          \"kind\": \"simulated\",\n          \"name\": \"Simulated call 1: Busy at work\",\n          \"source\": {\n            \"kind\": \"invented\",\n            \"index\": 0\n          },\n          \"scenario\": {\n            \"name\": \"Busy at work\",\n            \"persona\": \"Rahul, 34, drives a Swift and picks up on his way into a meeting.\",\n            \"goal\": \"Does not want to talk now, but would book the service later.\",\n            \"behaviour\": \"Short, slightly impatient answers. Says he is busy as soon as the service comes up.\",\n            \"language\": \"Hindi\",\n            \"variables\": {\n              \"due_date\": \"18 अगस्त\",\n              \"name\": \"राहुल\",\n              \"vehicle\": \"स्विफ्ट\"\n            }\n          },\n          \"transcript\": [\n            {\n              \"role\": \"agent\",\n              \"text\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात राहुल जी से हो रही है?\",\n              \"node_id\": \"identity\",\n              \"node_name\": \"Confirm the customer\"\n            },\n            {\n              \"role\": \"caller\",\n              \"text\": \"हां बोलिए, जल्दी बताइए.\"\n            },\n            {\n              \"role\": \"transition\",\n              \"text\": \"confirmed_identity\",\n              \"node_id\": \"offer_slot\",\n              \"node_name\": \"Book the service\"\n            },\n            {\n              \"role\": \"agent\",\n              \"text\": \"राहुल जी, आपकी स्विफ्ट की service 18 अगस्त को due है. आप किस दिन workshop आ पाएंगे?\",\n              \"node_id\": \"offer_slot\",\n              \"node_name\": \"Book the service\"\n            },\n            {\n              \"role\": \"caller\",\n              \"text\": \"अभी meeting में जा रहा हूं, अभी नहीं.\"\n            },\n            {\n              \"role\": \"agent\",\n              \"text\": \"कोई बात नहीं. आपको कब call करूं, आज शाम ठीक रहेगा?\",\n              \"node_id\": \"offer_slot\",\n              \"node_name\": \"Book the service\"\n            },\n            {\n              \"role\": \"caller\",\n              \"text\": \"हां, छह बजे के बाद कर लीजिए.\"\n            },\n            {\n              \"role\": \"transition\",\n              \"text\": \"not_now\",\n              \"node_id\": \"goodbye\",\n              \"node_name\": \"Close\"\n            },\n            {\n              \"role\": \"agent\",\n              \"text\": \"ठीक है राहुल जी, मैं आज छह बजे के बाद call करूंगा. धन्यवाद.\",\n              \"node_id\": \"goodbye\",\n              \"node_name\": \"Close\"\n            }\n          ],\n          \"nodes_visited\": [\n            \"Confirm the customer\",\n            \"Book the service\",\n            \"Close\"\n          ],\n          \"model\": \"voice-agent\",\n          \"ended\": \"end_node\",\n          \"estimated_secs\": 33\n        }\n      ],\n      \"findings\": [],\n      \"verdict\": \"ready\",\n      \"revised\": false,\n      \"revision_issues\": []\n    }\n  ],\n  \"found\": [\n    {\n      \"severity\": \"medium\",\n      \"title\": \"A busy caller is let go without a callback time\",\n      \"evidence\": \"Simulated call 1: the caller said \\\"अभी meeting में जा रहा हूं, अभी नहीं.\\\" and the agent called not_now at once and closed, so nobody knows when to call back.\",\n      \"fix\": \"In offer_slot, when the caller is busy, ask once when to call back before not_now, and extract the answer as callback_time.\",\n      \"nodes\": [\n        \"offer_slot\"\n      ]\n    }\n  ],\n  \"remaining\": [],\n  \"usage\": {\n    \"prompt_tokens\": 41870,\n    \"completion_tokens\": 8920\n  },\n  \"cost\": {\n    \"amount_inr\": 4.62\n  }\n}"
            },
            {
              "name": "200 — still running",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine",
                    "{{refine_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"frf_01KZR3Q5S89NTXQ40V3KYN4JMA\",\n  \"object\": \"flow_refinement\",\n  \"status\": \"running\",\n  \"stage\": \"simulating\",\n  \"progress\": {\n    \"round\": 1,\n    \"rounds\": 2,\n    \"tests_done\": 0,\n    \"tests_total\": 1\n  },\n  \"model\": \"gemini-3.8-flash\",\n  \"simulation_model\": \"voice-agent\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"input_flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"created_at\": \"2026-08-11T09:51:05Z\",\n  \"updated_at\": \"2026-08-11T09:51:19Z\",\n  \"finished_at\": null,\n  \"examples\": [],\n  \"calls\": [],\n  \"rounds\": [],\n  \"found\": [],\n  \"remaining\": [],\n  \"usage\": {\n    \"prompt_tokens\": 1920,\n    \"completion_tokens\": 1460\n  },\n  \"cost\": {\n    \"amount_inr\": 0.38\n  }\n}"
            },
            {
              "name": "404 — unknown id, another workspace's, or older than 24 hours",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine",
                    "{{refine_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no flow refinement frf_01KZR3Q5S89NTXQ40V3KYN4JMA\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get an agent's latest flow test",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow/refinement",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "flow",
                "refinement"
              ]
            },
            "description": "The most recent test started with this agent's `agent_id`, for 24 hours after it started. Handy when a test ran in the background and all you kept was the agent. Same object as Get a flow test."
          },
          "response": [
            {
              "name": "200 — the latest test",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow/refinement",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow",
                    "refinement"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"frf_01KZR3Q5S89NTXQ40V3KYN4JMA\",\n  \"object\": \"flow_refinement\",\n  \"status\": \"running\",\n  \"stage\": \"simulating\",\n  \"progress\": {\n    \"round\": 1,\n    \"rounds\": 2,\n    \"tests_done\": 0,\n    \"tests_total\": 1\n  },\n  \"model\": \"gemini-3.8-flash\",\n  \"simulation_model\": \"voice-agent\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"input_flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"created_at\": \"2026-08-11T09:51:05Z\",\n  \"updated_at\": \"2026-08-11T09:51:19Z\",\n  \"finished_at\": null,\n  \"examples\": [],\n  \"calls\": [],\n  \"rounds\": [],\n  \"found\": [],\n  \"remaining\": [],\n  \"usage\": {\n    \"prompt_tokens\": 1920,\n    \"completion_tokens\": 1460\n  },\n  \"cost\": {\n    \"amount_inr\": 0.38\n  }\n}"
            },
            {
              "name": "404 — no test for this agent",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow/refinement",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow",
                    "refinement"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent agt_01K2M4P7QRSTVWXYZ0A1B2C3 has no flow refinement\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Cancel a flow test",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "flow",
                "refine",
                "{{refine_id}}",
                "cancel"
              ]
            },
            "description": "Stops a running test at once. What the models had already done is charged, and the job ends `canceled` with the rounds that finished. Cancelling a job that has already ended changes nothing and returns it as it is."
          },
          "response": [
            {
              "name": "200 — canceled",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}/cancel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine",
                    "{{refine_id}}",
                    "cancel"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"frf_01KZR3Q5S89NTXQ40V3KYN4JMA\",\n  \"object\": \"flow_refinement\",\n  \"status\": \"canceled\",\n  \"stage\": \"simulating\",\n  \"progress\": {\n    \"round\": 1,\n    \"rounds\": 2,\n    \"tests_done\": 0,\n    \"tests_total\": 1\n  },\n  \"model\": \"gemini-3.8-flash\",\n  \"simulation_model\": \"voice-agent\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"input_flow_revision\": \"2c0eccdffdf0edca4e0a\",\n  \"created_at\": \"2026-08-11T09:51:05Z\",\n  \"updated_at\": \"2026-08-11T09:51:30Z\",\n  \"finished_at\": \"2026-08-11T09:51:30Z\",\n  \"examples\": [],\n  \"calls\": [],\n  \"rounds\": [],\n  \"found\": [],\n  \"remaining\": [],\n  \"usage\": {\n    \"prompt_tokens\": 1920,\n    \"completion_tokens\": 1460\n  },\n  \"cost\": {\n    \"amount_inr\": 0.38\n  }\n}"
            },
            {
              "name": "404 — unknown id, another workspace's, or older than 24 hours",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/flow/refine/{{refine_id}}/cancel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "flow",
                    "refine",
                    "{{refine_id}}",
                    "cancel"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no flow refinement frf_01KZR3Q5S89NTXQ40V3KYN4JMA\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Save a flow on an agent",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow?if_revision={{agent_revision}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "flow"
              ],
              "query": [
                {
                  "key": "if_revision",
                  "value": "{{agent_revision}}",
                  "description": "Optional. The agent revision you read."
                }
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          },\n          {\n            \"name\": \"callback_time\",\n            \"type\": \"string\",\n            \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n      }\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Replaces the agent's graph without resending the rest of the agent. It also turns a single-prompt agent into a node-based one. The body is the graph: here, the one the test above fixed.\n\nEach save is a new agent revision, so you can roll it back. `if_revision` refuses the save if the agent changed since you read it; this collection keeps it up to date from the last agent response. Problems come back as `invalid_flow` with their paths, including node tools that are not on_call tools of this agent. The new graph applies from the next call."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — the agent, now node-based",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow?if_revision={{agent_revision}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "{{agent_revision}}",
                      "description": "Optional. The agent revision you read."
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          },\n          {\n            \"name\": \"callback_time\",\n            \"type\": \"string\",\n            \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 5,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"is_start\": true,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            },\n            {\n              \"name\": \"callback_time\",\n              \"type\": \"string\",\n              \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"is_start\": false,\n          \"allow_interrupt\": false,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n        }\n      }\n    ]\n  },\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-08-11T09:56:02Z\"\n}"
            },
            {
              "name": "400 — a node offers a tool the agent does not have",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow?if_revision={{agent_revision}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "{{agent_revision}}",
                      "description": "Optional. The agent revision you read."
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          },\n          {\n            \"name\": \"callback_time\",\n            \"type\": \"string\",\n            \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"details\": [\n    {\n      \"path\": \"flow.nodes[2].data.tools[0]\",\n      \"message\": \"node \\\"offer_slot\\\" offers tool \\\"check_slots\\\", which is not an on_call tool of this agent; add it with phase on_call or remove it from the node\"\n    }\n  ],\n  \"error\": \"invalid_flow\"\n}"
            },
            {
              "name": "409 — the agent changed since you read it",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow?if_revision={{agent_revision}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "{{agent_revision}}",
                      "description": "Optional. The agent revision you read."
                    }
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"nodes\": [\n    {\n      \"id\": \"persona\",\n      \"type\": \"globalNode\",\n      \"data\": {\n        \"name\": \"Persona and rules\",\n        \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\"\n      }\n    },\n    {\n      \"id\": \"identity\",\n      \"type\": \"startCall\",\n      \"data\": {\n        \"name\": \"Confirm the customer\",\n        \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n        \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\"\n      }\n    },\n    {\n      \"id\": \"offer_slot\",\n      \"type\": \"agentNode\",\n      \"data\": {\n        \"name\": \"Book the service\",\n        \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n        \"extraction_enabled\": true,\n        \"extraction_variables\": [\n          {\n            \"name\": \"preferred_day\",\n            \"type\": \"string\",\n            \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n          },\n          {\n            \"name\": \"callback_time\",\n            \"type\": \"string\",\n            \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n          }\n        ]\n      }\n    },\n    {\n      \"id\": \"goodbye\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Close\",\n        \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n        \"allow_interrupt\": false\n      }\n    },\n    {\n      \"id\": \"not_customer\",\n      \"type\": \"endCall\",\n      \"data\": {\n        \"name\": \"Wrong person\",\n        \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\"\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"e1\",\n      \"source\": \"identity\",\n      \"target\": \"offer_slot\",\n      \"data\": {\n        \"label\": \"confirmed_identity\",\n        \"condition\": \"The caller confirmed they are the customer you asked for.\"\n      }\n    },\n    {\n      \"id\": \"e2\",\n      \"source\": \"identity\",\n      \"target\": \"not_customer\",\n      \"data\": {\n        \"label\": \"wrong_person\",\n        \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n      }\n    },\n    {\n      \"id\": \"e3\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"slot_booked\",\n        \"condition\": \"The customer named a day for the service and you read it back.\"\n      }\n    },\n    {\n      \"id\": \"e4\",\n      \"source\": \"offer_slot\",\n      \"target\": \"goodbye\",\n      \"data\": {\n        \"label\": \"not_now\",\n        \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"agent changed; read its current revision and retry\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get an agent's flow",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "flow"
              ]
            },
            "description": "The agent's graph, with what you need to save it back: `agent_revision` (send it as `if_revision`) and `flow_revision`, a fingerprint that changes whenever the graph does. A single-prompt agent has no graph, so it is a 404."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"agent_revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — the graph",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"flow\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"agent_revision\": 5,\n  \"flow_revision\": \"7ad7828b147804858dad\",\n  \"flow\": {\n    \"nodes\": [\n      {\n        \"id\": \"persona\",\n        \"type\": \"globalNode\",\n        \"data\": {\n          \"name\": \"Persona and rules\",\n          \"prompt\": \"You are Ashu, a service advisor at Mirai Motors.\\nSpeak everyday Hindi in Devanagari; common English words such as service, slot and workshop are fine.\\nSay one or two short sentences, then listen.\\nNever promise a discount, a price or a pickup.\\nWhen the condition of one of your functions is met, call it at once without saying anything first.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"identity\",\n        \"type\": \"startCall\",\n        \"data\": {\n          \"name\": \"Confirm the customer\",\n          \"prompt\": \"You have asked whether you are speaking with {{name}}. Wait for the answer.\\nIf they confirm, call confirmed_identity.\\nIf it is someone else or a wrong number, call wrong_person.\\nDo not mention the car or the service before they confirm.\",\n          \"greeting\": \"नमस्ते, मैं मिराई मोटर्स से आशु बोल रहा हूं. क्या मेरी बात {{name}} जी से हो रही है?\",\n          \"is_start\": true,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"offer_slot\",\n        \"type\": \"agentNode\",\n        \"data\": {\n          \"name\": \"Book the service\",\n          \"prompt\": \"Tell them their {{vehicle}} is due for service on {{due_date}}, and ask which day they can bring it to the workshop.\\nWhen they name a day, read it back once and call slot_booked.\\nIf they are busy, ask once when to call them back, then call not_now.\\nIf they do not want to book at all, call not_now.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": true,\n          \"extraction_variables\": [\n            {\n              \"name\": \"preferred_day\",\n              \"type\": \"string\",\n              \"prompt\": \"The day the customer chose for the service, in their words, for example Saturday or 20 August.\"\n            },\n            {\n              \"name\": \"callback_time\",\n              \"type\": \"string\",\n              \"prompt\": \"When the customer asked to be called back, in their words. Empty if they did not ask.\"\n            }\n          ]\n        }\n      },\n      {\n        \"id\": \"goodbye\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Close\",\n          \"prompt\": \"In one sentence, repeat what was agreed. Thank them and say goodbye. Do not ask anything else.\",\n          \"is_start\": false,\n          \"allow_interrupt\": false,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      },\n      {\n        \"id\": \"not_customer\",\n        \"type\": \"endCall\",\n        \"data\": {\n          \"name\": \"Wrong person\",\n          \"prompt\": \"Apologise for the trouble and say goodbye. Do not mention the car or the service.\",\n          \"is_start\": false,\n          \"allow_interrupt\": true,\n          \"add_global_prompt\": true,\n          \"extraction_enabled\": false,\n          \"extraction_variables\": []\n        }\n      }\n    ],\n    \"edges\": [\n      {\n        \"id\": \"e1\",\n        \"source\": \"identity\",\n        \"target\": \"offer_slot\",\n        \"data\": {\n          \"label\": \"confirmed_identity\",\n          \"condition\": \"The caller confirmed they are the customer you asked for.\"\n        }\n      },\n      {\n        \"id\": \"e2\",\n        \"source\": \"identity\",\n        \"target\": \"not_customer\",\n        \"data\": {\n          \"label\": \"wrong_person\",\n          \"condition\": \"The caller is someone else, or says it is a wrong number.\"\n        }\n      },\n      {\n        \"id\": \"e3\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"slot_booked\",\n          \"condition\": \"The customer named a day for the service and you read it back.\"\n        }\n      },\n      {\n        \"id\": \"e4\",\n        \"source\": \"offer_slot\",\n        \"target\": \"goodbye\",\n        \"data\": {\n          \"label\": \"not_now\",\n          \"condition\": \"The customer does not want to book now, and you have asked once when to call back if they were busy.\"\n        }\n      }\n    ]\n  }\n}"
            },
            {
              "name": "404 — a single-prompt agent",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/flow",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "flow"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent agt_01K2M4P7QRSTVWXYZ0A1B2C3 has no flow; it is a prompt agent\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Tools and secrets",
      "description": "Connect your own APIs to an agent. A tool runs at one of three moments:\n\n* `pre_call`, before dialling: fetch context for the greeting, or skip the call.\n* `on_call`, when the agent decides to use it mid-conversation: look something up, book something.\n* `post_call`, after the call has settled: send the outcome to your CRM, schedule a call back.\n\nThe order here is the order you'd use them in: see what's available, store your credential as a secret, add a tool, test it against your endpoint, then read each call's tool runs. Tools themselves cost nothing extra.\n\nTool definitions use Mirai's own templates, like `{{ args.date }}` and `{{ secrets.crm_key }}`. Postman may highlight them as unknown variables; they are sent as written, which is what you want.\n\nA definition that doesn't validate comes back as a list, so you can fix everything at once: `{\"error\": \"invalid_tools\", \"details\": [{\"path\", \"message\"}]}`. Everything else uses the usual `{\"error\": {\"code\", \"message\"}}`.",
      "item": [
        {
          "name": "Get tool catalog",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/tools/catalog",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "tools",
                "catalog"
              ]
            },
            "description": "What a tool can be. `data` lists the `http` kind and each builtin (`skip_call`, `end_call`, `schedule_callback`, `webhook`, plus `transfer_call` and `send_dtmf`, which are listed but not available yet) with its phases, settings schema and defaults. `phases` gives each phase's timeouts, retries and tool limit; `namespaces`, `operators` and `filters` are what templates and conditions can use.\n\n`model` and `native_tool_calls` tell you whether your tier's model can take on-call tools with arguments. Read-only, and calls nothing."
          },
          "response": [
            {
              "name": "200 — the catalog (lists shortened here)",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/tools/catalog",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "tools",
                    "catalog"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"name\": \"http\",\n      \"kind\": \"http\",\n      \"phases\": [\n        \"pre_call\",\n        \"on_call\",\n        \"post_call\"\n      ],\n      \"summary\": \"Call an https endpoint you own. URL, headers, query and body are templates over the call's namespaces; the reply can be transformed with jq and promoted into variables.\",\n      \"config_schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"method\": {\n            \"type\": \"string\",\n            \"enum\": [\n              \"GET\",\n              \"POST\",\n              \"PUT\",\n              \"PATCH\",\n              \"DELETE\"\n            ],\n            \"default\": \"GET\"\n          },\n          \"url\": {\n            \"type\": \"string\",\n            \"pattern\": \"^https://\",\n            \"maxLength\": 2048\n          },\n          \"headers\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": \"string\"\n            }\n          },\n          \"query\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": \"string\"\n            }\n          },\n          \"body\": {\n            \"description\": \"JSON template. A leaf that is exactly {{= path }} becomes the typed value.\"\n          }\n        },\n        \"required\": [\n          \"url\"\n        ]\n      },\n      \"defaults\": {\n        \"method\": \"GET\",\n        \"enabled\": true,\n        \"on_failure\": \"continue\",\n        \"execution\": \"sync\",\n        \"timeout_ms\": {\n          \"pre_call\": 5000,\n          \"on_call\": 10000,\n          \"post_call\": 15000\n        },\n        \"retry\": {\n          \"pre_call\": 0,\n          \"on_call\": 0,\n          \"post_call\": 2\n        }\n      },\n      \"tiers\": [\n        \"t1\",\n        \"t3\",\n        \"t5\"\n      ],\n      \"available\": true\n    },\n    {\n      \"name\": \"schedule_callback\",\n      \"kind\": \"builtin\",\n      \"phases\": [\n        \"on_call\",\n        \"post_call\"\n      ],\n      \"summary\": \"Book a later call to the same person. On_call supplies a default time and note argument schema; post_call uses configured templates. The scheduled call uses normal call admission.\",\n      \"config_schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"min_delay_minutes\": {\n            \"type\": \"integer\",\n            \"minimum\": 0,\n            \"default\": 30\n          },\n          \"max_days\": {\n            \"type\": \"integer\",\n            \"minimum\": 1,\n            \"default\": 14\n          },\n          \"at\": {\n            \"type\": \"string\",\n            \"description\": \"post_call only: an RFC3339 timestamp, usually a template such as {{ analysis.data.callback_at }}.\"\n          },\n          \"note\": {\n            \"type\": \"string\",\n            \"maxLength\": 500\n          }\n        }\n      },\n      \"defaults\": {\n        \"min_delay_minutes\": 30,\n        \"max_days\": 14\n      },\n      \"tiers\": [\n        \"t1\",\n        \"t3\",\n        \"t5\"\n      ],\n      \"available\": true\n    },\n    {\n      \"name\": \"transfer_call\",\n      \"kind\": \"builtin\",\n      \"phases\": [\n        \"on_call\"\n      ],\n      \"summary\": \"Hand the caller to a human or another number.\",\n      \"config_schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"to\": {\n            \"type\": \"string\",\n            \"pattern\": \"^\\\\+[1-9]\\\\d{7,14}$\"\n          },\n          \"mode\": {\n            \"type\": \"string\",\n            \"enum\": [\n              \"bridge\",\n              \"warm\"\n            ]\n          },\n          \"announce\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"to\"\n        ]\n      },\n      \"tiers\": [\n        \"t1\",\n        \"t3\",\n        \"t5\"\n      ],\n      \"requires\": [\n        \"telephony_transfer\"\n      ],\n      \"available\": false,\n      \"reason\": \"telephony support pending\"\n    }\n  ],\n  \"phases\": [\n    {\n      \"phase\": \"post_call\",\n      \"summary\": \"Runs after the call has settled and been billed. Never changes status, duration or the call.completed payload.\",\n      \"max_tools\": 10,\n      \"default_timeout_ms\": 15000,\n      \"max_timeout_ms\": 60000,\n      \"default_retries\": 2,\n      \"max_retries\": 5,\n      \"namespaces\": [\n        \"vars\",\n        \"call\",\n        \"now\",\n        \"tools\",\n        \"analysis\",\n        \"secrets (templates only)\"\n      ]\n    }\n  ],\n  \"execution_modes\": {\n    \"default\": \"sync\",\n    \"on_call_http\": [\n      \"sync\",\n      \"async\"\n    ],\n    \"async_timeout_max_ms\": 300000\n  },\n  \"namespaces\": {\n    \"vars\": \"Call input values, plus pre-call tool outputs as vars.<tool>.<key>.\",\n    \"call\": \"id, agent_id, to, from, tier, direction, channel, campaign_id, contact_id, attempt; after the call also status, ended_reason, duration_secs, answered.\",\n    \"args\": \"on_call only: the arguments the model supplied for this invocation.\"\n  },\n  \"operators\": [\n    {\n      \"op\": \"eq\",\n      \"means\": \"equal after trimming; numeric when both sides are numbers, boolean when both are true/false\"\n    },\n    {\n      \"op\": \"exists\",\n      \"means\": \"present and non-empty\"\n    },\n    {\n      \"op\": \"is_true\",\n      \"means\": \"one of true/1/yes/on\"\n    }\n  ],\n  \"filters\": [\n    \"default:\\\"fallback\\\"\",\n    \"json\",\n    \"urlencode\"\n  ],\n  \"limits\": {\n    \"tools_per_agent\": 40,\n    \"pre_call_tools\": 10,\n    \"on_call_tools\": 20,\n    \"post_call_tools\": 10,\n    \"runs_per_call\": 40,\n    \"response_bytes\": 262144,\n    \"promoted_value_chars\": 512,\n    \"select_keys\": 16,\n    \"url_chars\": 2048\n  },\n  \"tier\": \"t5\",\n  \"model\": \"miraiminds/mira-llm\",\n  \"native_tool_calls\": true,\n  \"text_style_models\": [\n    \"hinglish\"\n  ],\n  \"secrets_configured\": true\n}"
            }
          ]
        },
        {
          "name": "Store a secret",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "secrets",
                "{{secret_name}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"value\": \"REPLACE_WITH_YOUR_CRM_API_KEY\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Stores a credential for your tools to use as `{{ secrets.crm_key }}` in a header, query or body. Store it before you save a tool that uses it.\n\nWrite-only: the value is never returned or logged, and receipts show `«secret:crm_key»` in its place. PUT the same name again to rotate it. Names are lowercase letters, digits and `_`, starting with a letter (2–64 characters); a value is at most 4 KB. Secrets belong to the workspace, so every agent can use them."
          },
          "response": [
            {
              "name": "200 — stored",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "secrets",
                    "{{secret_name}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"value\": \"REPLACE_WITH_YOUR_CRM_API_KEY\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"secret\",\n  \"name\": \"crm_key\",\n  \"stored\": true\n}"
            },
            {
              "name": "400 — a name with capitals or a dash",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "secrets",
                    "{{secret_name}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"value\": \"REPLACE_WITH_YOUR_CRM_API_KEY\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"a secret name must be lowercase letters, digits and underscores, starting with a letter\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List secrets",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/secrets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "secrets"
              ]
            },
            "description": "The workspace's secret names and when each was stored or rotated. Never the values."
          },
          "response": [
            {
              "name": "200 — names only",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/secrets",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "secrets"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"name\": \"crm_key\",\n      \"key_id\": \"k_3f9a1c2e\",\n      \"created_at\": \"2026-10-09T08:40:12Z\",\n      \"updated_at\": \"2026-10-09T08:40:12Z\"\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Add or replace a tool",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "tools",
                "{{tool_name}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phase\": \"on_call\",\n  \"description\": \"Book a service slot for the customer's car.\",\n  \"when\": \"Use this once the customer has agreed to a date and a time. Confirm both before booking.\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"date\": {\n        \"type\": \"string\",\n        \"description\": \"Service date, YYYY-MM-DD.\"\n      },\n      \"time\": {\n        \"type\": \"string\",\n        \"description\": \"Slot start time, HH:MM, 24-hour.\"\n      }\n    },\n    \"required\": [\n      \"date\",\n      \"time\"\n    ]\n  },\n  \"speak_while\": \"एक सेकंड, मैं स्लॉट बुक कर रहा हूं.\",\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"https://api.example.com/service/bookings\",\n    \"headers\": {\n      \"Authorization\": \"Bearer {{ secrets.crm_key }}\"\n    },\n    \"body\": {\n      \"customer_id\": \"{{ vars.customer_id }}\",\n      \"date\": \"{{ args.date }}\",\n      \"time\": \"{{ args.time }}\"\n    }\n  },\n  \"response\": {\n    \"transform\": \"{booking_id, slot}\"\n  },\n  \"timeout_ms\": 8000\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Saves one tool on the agent, creating it or replacing the one with this name, and leaves the agent's other tools alone. The name comes from the URL (lowercase, 2–40 characters). Every save is a new agent revision, and calls already placed keep the version they started with.\n\nThis example is an on-call tool: the agent collects `date` and `time` from the caller, says the `speak_while` line, and POSTs them to your endpoint with your secret in the header. `{{ vars.customer_id }}` comes from the call's `variables`. Replace `request.url` with your own HTTPS endpoint (public, port 443).\n\nSend `if_revision` in the body to refuse the save if someone changed the agent since you read it. The answer is the whole agent, with every default filled in."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — saved: the agent, with its tools",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phase\": \"on_call\",\n  \"description\": \"Book a service slot for the customer's car.\",\n  \"when\": \"Use this once the customer has agreed to a date and a time. Confirm both before booking.\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"date\": {\n        \"type\": \"string\",\n        \"description\": \"Service date, YYYY-MM-DD.\"\n      },\n      \"time\": {\n        \"type\": \"string\",\n        \"description\": \"Slot start time, HH:MM, 24-hour.\"\n      }\n    },\n    \"required\": [\n      \"date\",\n      \"time\"\n    ]\n  },\n  \"speak_while\": \"एक सेकंड, मैं स्लॉट बुक कर रहा हूं.\",\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"https://api.example.com/service/bookings\",\n    \"headers\": {\n      \"Authorization\": \"Bearer {{ secrets.crm_key }}\"\n    },\n    \"body\": {\n      \"customer_id\": \"{{ vars.customer_id }}\",\n      \"date\": \"{{ args.date }}\",\n      \"time\": \"{{ args.time }}\"\n    }\n  },\n  \"response\": {\n    \"transform\": \"{booking_id, slot}\"\n  },\n  \"timeout_ms\": 8000\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 6,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [\n    {\n      \"name\": \"book_slot\",\n      \"phase\": \"on_call\",\n      \"kind\": \"http\",\n      \"enabled\": true,\n      \"description\": \"Book a service slot for the customer's car.\",\n      \"when\": \"Use this once the customer has agreed to a date and a time. Confirm both before booking.\",\n      \"parameters\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"date\": {\n            \"type\": \"string\",\n            \"description\": \"Service date, YYYY-MM-DD.\"\n          },\n          \"time\": {\n            \"type\": \"string\",\n            \"description\": \"Slot start time, HH:MM, 24-hour.\"\n          }\n        },\n        \"required\": [\n          \"date\",\n          \"time\"\n        ]\n      },\n      \"execution\": \"sync\",\n      \"speak_while\": \"एक सेकंड, मैं स्लॉट बुक कर रहा हूं.\",\n      \"request\": {\n        \"method\": \"POST\",\n        \"url\": \"https://api.example.com/service/bookings\",\n        \"headers\": {\n          \"Authorization\": \"Bearer {{ secrets.crm_key }}\"\n        },\n        \"body\": {\n          \"customer_id\": \"{{ vars.customer_id }}\",\n          \"date\": \"{{ args.date }}\",\n          \"time\": \"{{ args.time }}\"\n        }\n      },\n      \"response\": {\n        \"transform\": \"{booking_id, slot}\"\n      },\n      \"timeout_ms\": 8000,\n      \"retry\": {\n        \"attempts\": 0,\n        \"backoff_ms\": 500\n      },\n      \"on_failure\": \"continue\"\n    }\n  ],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-10-09T08:42:30Z\"\n}"
            },
            {
              "name": "400 — the secret it uses doesn't exist yet",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phase\": \"on_call\",\n  \"description\": \"Book a service slot for the customer's car.\",\n  \"when\": \"Use this once the customer has agreed to a date and a time. Confirm both before booking.\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"date\": {\n        \"type\": \"string\",\n        \"description\": \"Service date, YYYY-MM-DD.\"\n      },\n      \"time\": {\n        \"type\": \"string\",\n        \"description\": \"Slot start time, HH:MM, 24-hour.\"\n      }\n    },\n    \"required\": [\n      \"date\",\n      \"time\"\n    ]\n  },\n  \"speak_while\": \"एक सेकंड, मैं स्लॉट बुक कर रहा हूं.\",\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"https://api.example.com/service/bookings\",\n    \"headers\": {\n      \"Authorization\": \"Bearer {{ secrets.crm_key }}\"\n    },\n    \"body\": {\n      \"customer_id\": \"{{ vars.customer_id }}\",\n      \"date\": \"{{ args.date }}\",\n      \"time\": \"{{ args.time }}\"\n    }\n  },\n  \"response\": {\n    \"transform\": \"{booking_id, slot}\"\n  },\n  \"timeout_ms\": 8000\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": \"invalid_tools\",\n  \"details\": [\n    {\n      \"path\": \"tools[0].request.headers[\\\"Authorization\\\"]\",\n      \"message\": \"secret \\\"crm_key\\\" does not exist in this workspace; create it with PUT /v2/secrets/crm_key first\"\n    }\n  ]\n}"
            },
            {
              "name": "409 — if_revision is out of date",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phase\": \"on_call\",\n  \"description\": \"Book a service slot for the customer's car.\",\n  \"when\": \"Use this once the customer has agreed to a date and a time. Confirm both before booking.\",\n  \"parameters\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"date\": {\n        \"type\": \"string\",\n        \"description\": \"Service date, YYYY-MM-DD.\"\n      },\n      \"time\": {\n        \"type\": \"string\",\n        \"description\": \"Slot start time, HH:MM, 24-hour.\"\n      }\n    },\n    \"required\": [\n      \"date\",\n      \"time\"\n    ]\n  },\n  \"speak_while\": \"एक सेकंड, मैं स्लॉट बुक कर रहा हूं.\",\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"https://api.example.com/service/bookings\",\n    \"headers\": {\n      \"Authorization\": \"Bearer {{ secrets.crm_key }}\"\n    },\n    \"body\": {\n      \"customer_id\": \"{{ vars.customer_id }}\",\n      \"date\": \"{{ args.date }}\",\n      \"time\": \"{{ args.time }}\"\n    }\n  },\n  \"response\": {\n    \"transform\": \"{booking_id, slot}\"\n  },\n  \"timeout_ms\": 8000\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"agent changed; read its current revision and retry\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Test a tool",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}/test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "tools",
                "{{tool_name}}",
                "test"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"args\": {\n    \"date\": \"2026-10-18\",\n    \"time\": \"10:30\"\n  },\n  \"vars\": {\n    \"customer_id\": \"cus_42\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Runs the saved tool once, **for real, against your endpoint**, with values you supply, and shows exactly what happened: whether its condition held, the request as sent (secrets masked), the reply, what your `transform` made of it, what would be promoted, which template paths were empty, and whether a call would `run`, `skip` or `abort`. It places no call. Use test data for tools that book, charge or send messages.\n\nThe body is optional: `args` (what the model would pass), `vars`, `call` and `analysis`. Check `status` as well as the HTTP code: a tool that failed still comes back as a 200 with the failed run in it. With this folder's example URL the request can't connect; point the tool at your own endpoint first."
          },
          "response": [
            {
              "name": "200 — your endpoint answered",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"args\": {\n    \"date\": \"2026-10-18\",\n    \"time\": \"10:30\"\n  },\n  \"vars\": {\n    \"customer_id\": \"cus_42\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"tool\": \"book_slot\",\n  \"phase\": \"on_call\",\n  \"kind\": \"http\",\n  \"tool_run_id\": \"trun_4c7e19a0b25d83f6e0a91d58\",\n  \"condition\": {\n    \"result\": true,\n    \"failed_leaf\": \"\"\n  },\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"https://api.example.com/service/bookings\",\n    \"headers\": {\n      \"Authorization\": \"Bearer «secret:crm_key»\",\n      \"Content-Type\": \"application/json\"\n    },\n    \"body\": {\n      \"customer_id\": \"cus_42\",\n      \"date\": \"2026-10-18\",\n      \"time\": \"10:30\"\n    }\n  },\n  \"response\": {\n    \"status\": 200,\n    \"ms\": 240,\n    \"body_preview\": \"{\\\"booking_id\\\":\\\"bk_7731\\\",\\\"slot\\\":\\\"2026-10-18T10:30:00+05:30\\\",\\\"status\\\":\\\"confirmed\\\"}\"\n  },\n  \"transform\": {\n    \"output\": {\n      \"booking_id\": \"bk_7731\",\n      \"slot\": \"2026-10-18T10:30:00+05:30\"\n    }\n  },\n  \"promoted\": {},\n  \"missing\": [],\n  \"would\": \"run\",\n  \"status\": \"ok\"\n}"
            },
            {
              "name": "200 — your endpoint said 401",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"args\": {\n    \"date\": \"2026-10-18\",\n    \"time\": \"10:30\"\n  },\n  \"vars\": {\n    \"customer_id\": \"cus_42\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"tool\": \"book_slot\",\n  \"phase\": \"on_call\",\n  \"kind\": \"http\",\n  \"tool_run_id\": \"trun_4c7e19a0b25d83f6e0a91d58\",\n  \"condition\": {\n    \"result\": true,\n    \"failed_leaf\": \"\"\n  },\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"https://api.example.com/service/bookings\",\n    \"headers\": {\n      \"Authorization\": \"Bearer «secret:crm_key»\",\n      \"Content-Type\": \"application/json\"\n    },\n    \"body\": {\n      \"customer_id\": \"cus_42\",\n      \"date\": \"2026-10-18\",\n      \"time\": \"10:30\"\n    }\n  },\n  \"response\": {\n    \"status\": 401,\n    \"ms\": 182,\n    \"body_preview\": \"{\\\"error\\\":\\\"invalid token\\\"}\"\n  },\n  \"transform\": {\n    \"output\": null\n  },\n  \"promoted\": {},\n  \"missing\": [],\n  \"would\": \"run\",\n  \"status\": \"http_4xx\",\n  \"error\": {\n    \"code\": \"http_401\",\n    \"detail\": \"the endpoint answered 401\"\n  }\n}"
            },
            {
              "name": "404 — the agent has no tool by that name",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"args\": {\n    \"date\": \"2026-10-18\",\n    \"time\": \"10:30\"\n  },\n  \"vars\": {\n    \"customer_id\": \"cus_42\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent agt_01K2M4P7QRSTVWXYZ0A1B2C3 has no tool named \\\"book_slot\\\"\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Test a condition",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/conditions/test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "conditions",
                "test"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"condition\": {\n    \"all\": [\n      {\n        \"field\": \"vars.customer_id\",\n        \"op\": \"exists\"\n      },\n      {\n        \"field\": \"vars.do_not_call\",\n        \"op\": \"is_false\"\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"gte\",\n        \"value\": 10\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"lt\",\n        \"value\": 19\n      }\n    ]\n  },\n  \"scope\": {\n    \"vars\": {\n      \"customer_id\": \"cus_42\",\n      \"do_not_call\": \"false\"\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Checks a condition against values you supply and calls nothing. Use it while writing a tool's `condition`.\n\nCombine leaves with `all`, `any` and `not` (up to 8 levels, 64 comparisons). A leaf compares a dotted `field` from `vars`, `call`, `now`, `tools`, `args` or `analysis` using `op`; see the catalog for every operator. Leave `scope.now` out and it is filled in from the current time in Asia/Kolkata, as this example relies on. When the result is false, `failed_leaf` names the comparison that decided it."
          },
          "response": [
            {
              "name": "200 — true: inside calling hours",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/conditions/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "conditions",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"condition\": {\n    \"all\": [\n      {\n        \"field\": \"vars.customer_id\",\n        \"op\": \"exists\"\n      },\n      {\n        \"field\": \"vars.do_not_call\",\n        \"op\": \"is_false\"\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"gte\",\n        \"value\": 10\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"lt\",\n        \"value\": 19\n      }\n    ]\n  },\n  \"scope\": {\n    \"vars\": {\n      \"customer_id\": \"cus_42\",\n      \"do_not_call\": \"false\"\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"result\": true,\n  \"failed_leaf\": \"\",\n  \"condition\": {\n    \"all\": [\n      {\n        \"field\": \"vars.customer_id\",\n        \"op\": \"exists\"\n      },\n      {\n        \"field\": \"vars.do_not_call\",\n        \"op\": \"is_false\"\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"gte\",\n        \"value\": 10\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"lt\",\n        \"value\": 19\n      }\n    ]\n  },\n  \"now\": {\n    \"iso\": \"2026-10-09T14:30:00+05:30\",\n    \"date\": \"2026-10-09\",\n    \"time\": \"14:30\",\n    \"hour\": 14,\n    \"minute\": 30,\n    \"weekday\": \"Friday\",\n    \"weekday_num\": 5,\n    \"is_weekend\": false,\n    \"month\": 10,\n    \"year\": 2026,\n    \"epoch\": 1791536400,\n    \"timezone\": \"Asia/Kolkata\",\n    \"greeting\": \"Good afternoon\"\n  }\n}"
            },
            {
              "name": "200 — false: after 7 pm",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/conditions/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "conditions",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"condition\": {\n    \"all\": [\n      {\n        \"field\": \"vars.customer_id\",\n        \"op\": \"exists\"\n      },\n      {\n        \"field\": \"vars.do_not_call\",\n        \"op\": \"is_false\"\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"gte\",\n        \"value\": 10\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"lt\",\n        \"value\": 19\n      }\n    ]\n  },\n  \"scope\": {\n    \"vars\": {\n      \"customer_id\": \"cus_42\",\n      \"do_not_call\": \"false\"\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"result\": false,\n  \"failed_leaf\": \"now.hour lt 19 (got \\\"21\\\")\",\n  \"condition\": {\n    \"all\": [\n      {\n        \"field\": \"vars.customer_id\",\n        \"op\": \"exists\"\n      },\n      {\n        \"field\": \"vars.do_not_call\",\n        \"op\": \"is_false\"\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"gte\",\n        \"value\": 10\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"lt\",\n        \"value\": 19\n      }\n    ]\n  },\n  \"now\": {\n    \"iso\": \"2026-10-09T21:10:00+05:30\",\n    \"date\": \"2026-10-09\",\n    \"time\": \"21:10\",\n    \"hour\": 21,\n    \"minute\": 10,\n    \"weekday\": \"Friday\",\n    \"weekday_num\": 5,\n    \"is_weekend\": false,\n    \"month\": 10,\n    \"year\": 2026,\n    \"epoch\": 1791560400,\n    \"timezone\": \"Asia/Kolkata\",\n    \"greeting\": \"Good evening\"\n  }\n}"
            },
            {
              "name": "400 — an operator spelled the wrong way",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/conditions/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "conditions",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"condition\": {\n    \"all\": [\n      {\n        \"field\": \"vars.customer_id\",\n        \"op\": \"exists\"\n      },\n      {\n        \"field\": \"vars.do_not_call\",\n        \"op\": \"is_false\"\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"gte\",\n        \"value\": 10\n      },\n      {\n        \"field\": \"now.hour\",\n        \"op\": \"lt\",\n        \"value\": 19\n      }\n    ]\n  },\n  \"scope\": {\n    \"vars\": {\n      \"customer_id\": \"cus_42\",\n      \"do_not_call\": \"false\"\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": \"invalid_tools\",\n  \"details\": [\n    {\n      \"path\": \"condition.all[2].op\",\n      \"message\": \"unknown operator \\\">=\\\" (did you mean \\\"gte\\\"?)\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "List a call's tool runs",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/calls/{{call_id}}/tool_runs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "{{call_id}}",
                "tool_runs"
              ]
            },
            "description": "Every tool that ran on one call, in order, before, during and after it: which tool, when, how long, what its condition decided, the request (secrets masked) and what came back. Read it when a tool was skipped, timed out, or returned something unexpected, or to get a background tool's result that arrived after the caller hung up.\n\n`status` is `ok`, `skipped`, `http_4xx`, `http_5xx`, `timeout`, `egress_denied`, `transform_failed`, `budget_exhausted`, `disabled` or `failed`; `error` has the precise code, such as `http_502`. A `schedule_callback` run's `result` carries the `callback_id`. A call with no tool runs, or one that isn't yours, returns an empty list."
          },
          "response": [
            {
              "name": "200 — one on-call run",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/calls/{{call_id}}/tool_runs",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "{{call_id}}",
                    "tool_runs"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"tool_run_id\": \"trun_9b41e6d07c25af83d10e5b72\",\n      \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n      \"name\": \"book_slot\",\n      \"phase\": \"on_call\",\n      \"kind\": \"http\",\n      \"seq\": 0,\n      \"attempt\": 1,\n      \"status\": \"ok\",\n      \"http_status\": 200,\n      \"started_at\": \"2026-10-09T09:16:02.418532Z\",\n      \"ended_at\": \"2026-10-09T09:16:02.659107Z\",\n      \"ms\": 240,\n      \"request\": {\n        \"method\": \"POST\",\n        \"url\": \"https://api.example.com/service/bookings\",\n        \"headers\": {\n          \"Authorization\": \"Bearer «secret:crm_key»\",\n          \"Content-Type\": \"application/json\"\n        },\n        \"body\": {\n          \"customer_id\": \"cus_42\",\n          \"date\": \"2026-10-18\",\n          \"time\": \"10:30\"\n        }\n      },\n      \"result\": {\n        \"booking_id\": \"bk_7731\",\n        \"slot\": \"2026-10-18T10:30:00+05:30\"\n      },\n      \"body_preview\": \"{\\\"booking_id\\\":\\\"bk_7731\\\",\\\"slot\\\":\\\"2026-10-18T10:30:00+05:30\\\",\\\"status\\\":\\\"confirmed\\\"}\"\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Cancel a scheduled callback",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/callbacks/{{callback_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "callbacks",
                "{{callback_id}}"
              ]
            },
            "description": "Cancels a call back an agent promised with the `schedule_callback` tool, before it dials. Find the `callback_id` in that tool's `result` in the call's tool runs. 204 when it is cancelled. 404 once it has been dialled, if it was already cancelled, or if it isn't yours."
          },
          "response": [
            {
              "name": "204 — cancelled",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/callbacks/{{callback_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "callbacks",
                    "{{callback_id}}"
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            },
            {
              "name": "404 — already dialled, or already cancelled",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/callbacks/{{callback_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "callbacks",
                    "{{callback_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no scheduled callback cbk_5f2a9c0e71d34b8a6e19c047\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Remove a tool",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "agents",
                "{{agent_id}}",
                "tools",
                "{{tool_name}}"
              ],
              "query": [
                {
                  "key": "if_revision",
                  "value": "{{agent_revision}}",
                  "description": "Only remove it if the agent is still at this revision.",
                  "disabled": true
                }
              ]
            },
            "description": "Takes one tool off the agent and leaves the rest. Like any save, it creates a new revision, and calls already placed keep the tool. Turn on `if_revision` to refuse the change if the agent moved on since you read it. The answer is the updated agent."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const agent_revision = pick(\"revision\");",
                  "  if (agent_revision != null && agent_revision !== '') pm.collectionVariables.set(\"agent_revision\", String(agent_revision));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — removed: the agent, without it",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "{{agent_revision}}",
                      "description": "Only remove it if the agent is still at this revision.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"revision\": 7,\n  \"draft\": false,\n  \"archived\": false,\n  \"analysis\": {\n    \"enabled\": false\n  },\n  \"id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"object\": \"agent\",\n  \"name\": \"सर्विस रिमाइंडर\",\n  \"system_prompt\": \"आप आशु हैं, मिराई मोटर्स के सर्विस एडवाइज़र. {{name}} जी की {{vehicle}} की सर्विस {{due_date}} को ड्यू है. हिंदी में बात करें, छोटे वाक्य बोलें, और ग्राहक से सर्विस की तारीख कन्फर्म करें.\",\n  \"first_message\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\",\n  \"voice\": {\n    \"voice_id\": \"ashu\",\n    \"language\": \"hi\"\n  },\n  \"language\": \"hi\",\n  \"max_duration_secs\": 300,\n  \"end_call\": {\n    \"enabled\": true,\n    \"message\": \"धन्यवाद, आपका दिन शुभ हो.\",\n    \"confirm\": true\n  },\n  \"voicemail\": {\n    \"action\": \"hangup\"\n  },\n  \"background_sound\": {\n    \"sound\": \"off\"\n  },\n  \"behavior\": {\n    \"interruptions\": \"normal\",\n    \"adaptive_interruptions\": true,\n    \"pass_through\": [],\n    \"date_awareness\": true\n  },\n  \"secondary_languages\": [\n    \"en\"\n  ],\n  \"keyterms\": [\n    \"मिराई मोटर्स\",\n    \"Swift\",\n    \"आशु\"\n  ],\n  \"tools\": [],\n  \"created_at\": \"2026-08-11T09:14:02Z\",\n  \"updated_at\": \"2026-10-09T11:05:40Z\"\n}"
            },
            {
              "name": "404 — the agent has no tool by that name",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/agents/{{agent_id}}/tools/{{tool_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "agents",
                    "{{agent_id}}",
                    "tools",
                    "{{tool_name}}"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "{{agent_revision}}",
                      "description": "Only remove it if the agent is still at this revision.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent agt_01K2M4P7QRSTVWXYZ0A1B2C3 has no tool named \\\"book_slot\\\"\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete a secret",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "secrets",
                "{{secret_name}}"
              ]
            },
            "description": "Deletes a secret for good. A secret that an agent's tools still use is refused with a 409 that lists those agents, because deleting it would make every one of their calls fail that tool. Remove the references first (*Remove a tool*, or edit the tool), then delete."
          },
          "response": [
            {
              "name": "204 — deleted",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "secrets",
                    "{{secret_name}}"
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            },
            {
              "name": "409 — a tool still uses it",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "secrets",
                    "{{secret_name}}"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"secret_in_use\",\n    \"message\": \"secret \\\"crm_key\\\" is still used by agt_01K2M4P7QRSTVWXYZ0A1B2C3; remove it from those agents' tools first\"\n  },\n  \"agent_ids\": [\n    \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  ]\n}"
            },
            {
              "name": "404 — no secret by that name",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/secrets/{{secret_name}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "secrets",
                    "{{secret_name}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no secret named \\\"crm_key\\\"\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Webhooks",
      "description": "Get call events at your own HTTPS URL, signed, retried and kept for 30 days.\n\n1. *Create a destination* with your URL. Save the `signing_secret` from that answer: it is shown once.\n2. *Subscribe a destination to events*, for one agent or the whole workspace. `call.completed` arrives when a call ends; `call.processing.completed` when the recording, transcript, results and post-call tools have all settled.\n3. *Send a test event*. It is a real POST to your URL with made-up call data and `test: true`. No call is placed.\n\nEvery request carries `X-Mirai-Signature: t=<unix>,v1=<hex>`, an HMAC-SHA256 of `<unix>.<raw body>`, and `X-Mirai-Signed-With`, which names the secret that signed it. A destination's requests are signed with its own Destination secret; the `webhook_url` you pass when creating a call is signed with your Call webhook secret, the one shown with your API keys. A URL that is both gets each event once, with one secret. Delivery is at least once, so keep each event `id` and skip ones you've already handled.\n\nChanges send the resource's current `revision` (`if_revision`); a stale one is a 409 and changes nothing. Until the webhook release reaches your workspace these routes answer 404. The same settings are in the console under Webhooks, and on each agent in Agent Studio.",
      "item": [
        {
          "name": "List event types",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/event-types",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "event-types"
              ]
            },
            "description": "Every event you can subscribe to, in display order, with its group, a plain description, its JSON schema and a sample payload."
          },
          "response": [
            {
              "name": "200 — the catalogue",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/event-types",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "event-types"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"type\": \"call.completed\",\n      \"label\": \"Call completed\",\n      \"group\": \"call\",\n      \"description\": \"The call ended normally. Analysis and post-call actions may still be running.\",\n      \"schema\": {\n        \"type\": \"object\"\n      },\n      \"example\": {\n        \"id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n        \"type\": \"call.completed\",\n        \"created_at\": \"2026-10-10T06:30:12.481Z\",\n        \"schema_version\": \"2026-09-22\",\n        \"workspace_id\": \"ws_example\",\n        \"subject\": {\n          \"type\": \"call\",\n          \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\"\n        },\n        \"source_id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1:processing:1\",\n        \"test\": true,\n        \"data\": {\n          \"call\": {\n            \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\",\n            \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n            \"status\": \"completed\"\n          },\n          \"processing\": {\n            \"version\": 1,\n            \"state\": \"completed\",\n            \"outcome\": \"completed\",\n            \"stages\": {\n              \"analysis\": {\n                \"state\": \"completed\",\n                \"generation\": 1\n              },\n              \"recording\": {\n                \"state\": \"completed\",\n                \"generation\": 1\n              },\n              \"transcript\": {\n                \"state\": \"completed\",\n                \"generation\": 1\n              },\n              \"post_call_tools\": {\n                \"state\": \"skipped\",\n                \"generation\": 1\n              }\n            }\n          }\n        }\n      }\n    },\n    {\n      \"type\": \"call.processing.completed\",\n      \"label\": \"All processing finished\",\n      \"group\": \"processing\",\n      \"description\": \"Recording, transcript, analysis and post-call actions have all finished, including any failures.\",\n      \"schema\": {\n        \"type\": \"object\"\n      },\n      \"example\": {\n        \"id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n        \"type\": \"call.processing.completed\",\n        \"created_at\": \"2026-10-10T06:30:12.481Z\",\n        \"schema_version\": \"2026-09-22\",\n        \"workspace_id\": \"ws_example\",\n        \"subject\": {\n          \"type\": \"call\",\n          \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\"\n        },\n        \"source_id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1:processing:1\",\n        \"test\": true,\n        \"data\": {\n          \"call\": {\n            \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\",\n            \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n            \"status\": \"completed\"\n          },\n          \"processing\": {\n            \"version\": 1,\n            \"state\": \"completed\",\n            \"outcome\": \"completed\",\n            \"stages\": {\n              \"analysis\": {\n                \"state\": \"completed\",\n                \"generation\": 1\n              },\n              \"recording\": {\n                \"state\": \"completed\",\n                \"generation\": 1\n              },\n              \"transcript\": {\n                \"state\": \"completed\",\n                \"generation\": 1\n              },\n              \"post_call_tools\": {\n                \"state\": \"skipped\",\n                \"generation\": 1\n              }\n            }\n          }\n        }\n      }\n    }\n  ],\n  \"has_more\": false\n}"
            },
            {
              "name": "404 — not on this workspace yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/event-types",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "event-types"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Webhooks are not available on this workspace yet.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Create a destination",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "webhook-setup-2026-10-10-01",
                "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Customer CRM\",\n  \"url\": \"https://crm.example.com/mirai/webhooks\",\n  \"headers\": {\n    \"Authorization\": \"Bearer REPLACE_ME\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "A reusable HTTPS address (port 443) that events are POSTed to. Optional `headers` (up to 16) are stored encrypted; reads only show their names.\n\nThe answer includes `signing_secret`. Store it in your server's environment now; ordinary reads never return it."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const webhook_endpoint_id = pick(\"id\");",
                  "  if (webhook_endpoint_id != null && webhook_endpoint_id !== '') pm.collectionVariables.set(\"webhook_endpoint_id\", String(webhook_endpoint_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — created",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Customer CRM\",\n  \"url\": \"https://crm.example.com/mirai/webhooks\",\n  \"headers\": {\n    \"Authorization\": \"Bearer REPLACE_ME\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"object\": \"webhook_endpoint\",\n  \"name\": \"Customer CRM\",\n  \"url\": \"https://crm.example.com/mirai/webhooks\",\n  \"method\": \"POST\",\n  \"header_names\": [\n    \"Authorization\"\n  ],\n  \"enabled\": true,\n  \"revision\": 1,\n  \"created_at\": \"2026-10-10T06:30:12.481Z\",\n  \"signing_secret\": \"whsec_REPLACE_ME\",\n  \"signing_key_version\": 1\n}"
            },
            {
              "name": "400 — not an HTTPS URL",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Customer CRM\",\n  \"url\": \"https://crm.example.com/mirai/webhooks\",\n  \"headers\": {\n    \"Authorization\": \"Bearer REPLACE_ME\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"url must be an https URL on port 443\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List destinations",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100; 20 when left out",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Every destination in the workspace. Header values and signing secrets are never shown."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 20 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"object\": \"webhook_endpoint\",\n      \"name\": \"Customer CRM\",\n      \"url\": \"https://crm.example.com/mirai/webhooks\",\n      \"method\": \"POST\",\n      \"header_names\": [\n        \"Authorization\"\n      ],\n      \"enabled\": true,\n      \"revision\": 1,\n      \"created_at\": \"2026-10-10T06:30:12.481Z\"\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Get a destination",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints",
                "{{webhook_endpoint_id}}"
              ]
            },
            "description": "One destination with its `revision` and recent delivery health."
          },
          "response": [
            {
              "name": "200 — the destination",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"object\": \"webhook_endpoint\",\n  \"name\": \"Customer CRM\",\n  \"url\": \"https://crm.example.com/mirai/webhooks\",\n  \"method\": \"POST\",\n  \"header_names\": [\n    \"Authorization\"\n  ],\n  \"enabled\": true,\n  \"revision\": 1,\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Webhook resource not found.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Update a destination",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints",
                "{{webhook_endpoint_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": 1,\n  \"url\": \"https://crm.example.com/mirai/v2/webhooks\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Rename it, move it to a new URL, replace its headers or pause it (`enabled: false`). Pausing holds queued requests; their 24-hour deadline keeps running. Send the current `if_revision`."
          },
          "response": [
            {
              "name": "200 — updated",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"url\": \"https://crm.example.com/mirai/v2/webhooks\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"object\": \"webhook_endpoint\",\n  \"name\": \"Customer CRM\",\n  \"url\": \"https://crm.example.com/mirai/v2/webhooks\",\n  \"method\": \"POST\",\n  \"header_names\": [\n    \"Authorization\"\n  ],\n  \"enabled\": true,\n  \"revision\": 2,\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            },
            {
              "name": "409 — stale revision",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"url\": \"https://crm.example.com/mirai/v2/webhooks\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The resource changed since you read it. Read it again, then retry with its revision.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete a destination",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}?if_revision=1",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints",
                "{{webhook_endpoint_id}}"
              ],
              "query": [
                {
                  "key": "if_revision",
                  "value": "1",
                  "description": "the destination's current revision"
                }
              ]
            },
            "description": "Removes it and its subscriptions and cancels unsent requests. Delivery history stays for 30 days."
          },
          "response": [
            {
              "name": "204 — deleted",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}?if_revision=1",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "1",
                      "description": "the destination's current revision"
                    }
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            },
            {
              "name": "409 — stale revision",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}?if_revision=1",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "1",
                      "description": "the destination's current revision"
                    }
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The resource changed since you read it. Read it again, then retry with its revision.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Rotate the signing secret",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "webhook-setup-2026-10-10-01",
                "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}/rotate-secret",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints",
                "{{webhook_endpoint_id}}",
                "rotate-secret"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Issues a new secret that starts signing five minutes later. Install it before then and accept both for the switch; keep the old one for an hour."
          },
          "response": [
            {
              "name": "200 — new secret",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}/rotate-secret",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}",
                    "rotate-secret"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"revision\": 2,\n  \"signing_secret\": \"whsec_REPLACE_ME\",\n  \"signing_key_version\": 2,\n  \"activates_at\": \"2026-10-10T06:35:12.481Z\"\n}"
            },
            {
              "name": "409 — a rotation is already pending",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}/rotate-secret",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}",
                    "rotate-secret"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"rotation_pending\",\n    \"message\": \"A signing-secret rotation is already pending.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Send a test event",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "webhook-setup-2026-10-10-01",
                "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}/test",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "endpoints",
                "{{webhook_endpoint_id}}",
                "test"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": 1,\n  \"event_type\": \"call.processing.completed\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Queues one signed event with made-up call data and `test: true`, sent for real to the destination's URL. No call is placed. The answer is the queued delivery; read it (and its attempts) to see what your server said."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const webhook_delivery_id = pick(\"id\");",
                  "  if (webhook_delivery_id != null && webhook_delivery_id !== '') pm.collectionVariables.set(\"webhook_delivery_id\", String(webhook_delivery_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "202 — queued",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/endpoints/{{webhook_endpoint_id}}/test",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "endpoints",
                    "{{webhook_endpoint_id}}",
                    "test"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"event_type\": \"call.processing.completed\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5\",\n  \"object\": \"webhook_delivery\",\n  \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"endpoint_revision\": 1,\n  \"subscription_ids\": [\n    \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\"\n  ],\n  \"state\": \"pending\",\n  \"revision\": 1,\n  \"cycle\": 1,\n  \"attempts\": 0,\n  \"cycle_attempts\": 0,\n  \"last_http_status\": 0,\n  \"next_attempt_at\": \"2026-10-10T06:30:12.481Z\",\n  \"deadline\": \"2026-10-11T06:30:12.481Z\",\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            }
          ]
        },
        {
          "name": "Subscribe a destination to events",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "webhook-setup-2026-10-10-01",
                "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/subscriptions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "subscriptions"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"endpoint_id\": \"{{webhook_endpoint_id}}\",\n  \"scope\": {\n    \"type\": \"agent\",\n    \"agent_id\": \"{{agent_id}}\"\n  },\n  \"event_types\": [\n    \"call.completed\",\n    \"call.processing.completed\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Which events go to a destination, for one agent (`scope.type: agent`) or every agent in the workspace (`scope.type: workspace`). Inbound and outbound calls both count. Overlapping subscriptions to the same destination send one copy."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const webhook_subscription_id = pick(\"id\");",
                  "  if (webhook_subscription_id != null && webhook_subscription_id !== '') pm.collectionVariables.set(\"webhook_subscription_id\", String(webhook_subscription_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — subscribed",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/subscriptions",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "subscriptions"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"endpoint_id\": \"{{webhook_endpoint_id}}\",\n  \"scope\": {\n    \"type\": \"agent\",\n    \"agent_id\": \"{{agent_id}}\"\n  },\n  \"event_types\": [\n    \"call.completed\",\n    \"call.processing.completed\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\",\n  \"object\": \"webhook_subscription\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"scope\": {\n    \"type\": \"agent\",\n    \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  },\n  \"event_types\": [\n    \"call.completed\",\n    \"call.processing.completed\"\n  ],\n  \"enabled\": true,\n  \"revision\": 1,\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            }
          ]
        },
        {
          "name": "List subscriptions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/subscriptions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "subscriptions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100; 20 when left out",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                },
                {
                  "key": "endpoint_id",
                  "value": "{{webhook_endpoint_id}}",
                  "disabled": true
                },
                {
                  "key": "agent_id",
                  "value": "{{agent_id}}",
                  "disabled": true
                }
              ]
            },
            "description": "Every subscription, optionally for one destination or agent."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/subscriptions",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "subscriptions"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 20 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    },
                    {
                      "key": "endpoint_id",
                      "value": "{{webhook_endpoint_id}}",
                      "disabled": true
                    },
                    {
                      "key": "agent_id",
                      "value": "{{agent_id}}",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"id\": \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\",\n      \"object\": \"webhook_subscription\",\n      \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"scope\": {\n        \"type\": \"agent\",\n        \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n      },\n      \"event_types\": [\n        \"call.completed\",\n        \"call.processing.completed\"\n      ],\n      \"enabled\": true,\n      \"revision\": 1,\n      \"created_at\": \"2026-10-10T06:30:12.481Z\"\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Get a subscription",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "subscriptions",
                "{{webhook_subscription_id}}"
              ]
            },
            "description": "One subscription and its `revision`."
          },
          "response": [
            {
              "name": "200 — the subscription",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "subscriptions",
                    "{{webhook_subscription_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\",\n  \"object\": \"webhook_subscription\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"scope\": {\n    \"type\": \"agent\",\n    \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  },\n  \"event_types\": [\n    \"call.completed\",\n    \"call.processing.completed\"\n  ],\n  \"enabled\": true,\n  \"revision\": 1,\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            }
          ]
        },
        {
          "name": "Change events or pause",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "subscriptions",
                "{{webhook_subscription_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": 1,\n  \"event_types\": [\n    \"call.completed\",\n    \"call.analysis.completed\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Replace `event_types`, or pause with `enabled: false` (requests already queued still go). The destination and scope can't change: make another subscription."
          },
          "response": [
            {
              "name": "200 — updated",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "subscriptions",
                    "{{webhook_subscription_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"event_types\": [\n    \"call.completed\",\n    \"call.analysis.completed\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\",\n  \"object\": \"webhook_subscription\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"scope\": {\n    \"type\": \"agent\",\n    \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\"\n  },\n  \"event_types\": [\n    \"call.completed\",\n    \"call.analysis.completed\"\n  ],\n  \"enabled\": true,\n  \"revision\": 2,\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            },
            {
              "name": "409 — stale revision",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "subscriptions",
                    "{{webhook_subscription_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"event_types\": [\n    \"call.completed\",\n    \"call.analysis.completed\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The resource changed since you read it. Read it again, then retry with its revision.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete a subscription",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}?if_revision=1",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "subscriptions",
                "{{webhook_subscription_id}}"
              ],
              "query": [
                {
                  "key": "if_revision",
                  "value": "1",
                  "description": "the subscription's current revision"
                }
              ]
            },
            "description": "Stops future matches. Deliveries already made keep their history."
          },
          "response": [
            {
              "name": "204 — deleted",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/subscriptions/{{webhook_subscription_id}}?if_revision=1",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "subscriptions",
                    "{{webhook_subscription_id}}"
                  ],
                  "query": [
                    {
                      "key": "if_revision",
                      "value": "1",
                      "description": "the subscription's current revision"
                    }
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            }
          ]
        },
        {
          "name": "List events",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/events",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "events"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100; 20 when left out",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                },
                {
                  "key": "agent_id",
                  "value": "{{agent_id}}",
                  "disabled": true
                },
                {
                  "key": "event_type",
                  "value": "call.completed",
                  "disabled": true
                }
              ]
            },
            "description": "Every event in the last 30 days, including ones no subscription matched."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/events",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "events"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 20 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    },
                    {
                      "key": "agent_id",
                      "value": "{{agent_id}}",
                      "disabled": true
                    },
                    {
                      "key": "event_type",
                      "value": "call.completed",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n      \"type\": \"call.processing.completed\",\n      \"created_at\": \"2026-10-10T06:30:12.481Z\",\n      \"schema_version\": \"2026-09-22\",\n      \"workspace_id\": \"ws_example\",\n      \"subject\": {\n        \"type\": \"call\",\n        \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\"\n      },\n      \"source_id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1:processing:1\",\n      \"test\": false,\n      \"data\": {\n        \"call\": {\n          \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\",\n          \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n          \"status\": \"completed\"\n        },\n        \"processing\": {\n          \"version\": 1,\n          \"state\": \"completed\",\n          \"outcome\": \"completed\",\n          \"stages\": {\n            \"analysis\": {\n              \"state\": \"completed\",\n              \"generation\": 1\n            },\n            \"recording\": {\n              \"state\": \"completed\",\n              \"generation\": 1\n            },\n            \"transcript\": {\n              \"state\": \"completed\",\n              \"generation\": 1\n            },\n            \"post_call_tools\": {\n              \"state\": \"skipped\",\n              \"generation\": 1\n            }\n          }\n        }\n      }\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Get an event",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/events/{{webhook_event_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "events",
                "{{webhook_event_id}}"
              ]
            },
            "description": "The exact event body that was signed and sent. Kept for 30 days."
          },
          "response": [
            {
              "name": "200 — the event",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/events/{{webhook_event_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "events",
                    "{{webhook_event_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n  \"type\": \"call.processing.completed\",\n  \"created_at\": \"2026-10-10T06:30:12.481Z\",\n  \"schema_version\": \"2026-09-22\",\n  \"workspace_id\": \"ws_example\",\n  \"subject\": {\n    \"type\": \"call\",\n    \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\"\n  },\n  \"source_id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1:processing:1\",\n  \"test\": false,\n  \"data\": {\n    \"call\": {\n      \"id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"status\": \"completed\"\n    },\n    \"processing\": {\n      \"version\": 1,\n      \"state\": \"completed\",\n      \"outcome\": \"completed\",\n      \"stages\": {\n        \"analysis\": {\n          \"state\": \"completed\",\n          \"generation\": 1\n        },\n        \"recording\": {\n          \"state\": \"completed\",\n          \"generation\": 1\n        },\n        \"transcript\": {\n          \"state\": \"completed\",\n          \"generation\": 1\n        },\n        \"post_call_tools\": {\n          \"state\": \"skipped\",\n          \"generation\": 1\n        }\n      }\n    }\n  }\n}"
            },
            {
              "name": "404 — expired or unknown",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/events/{{webhook_event_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "events",
                    "{{webhook_event_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Webhook resource not found.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List deliveries",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/deliveries",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "deliveries"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100; 20 when left out",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                },
                {
                  "key": "agent_id",
                  "value": "{{agent_id}}",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "failed",
                  "disabled": true
                }
              ]
            },
            "description": "What was sent where, and how it went. Filter by destination, agent, call, event or status."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const webhook_delivery_id = pick(\"data.0.id\");",
                  "  if (webhook_delivery_id != null && webhook_delivery_id !== '') pm.collectionVariables.set(\"webhook_delivery_id\", String(webhook_delivery_id));",
                  "  const webhook_event_id = pick(\"data.0.event_id\");",
                  "  if (webhook_event_id != null && webhook_event_id !== '') pm.collectionVariables.set(\"webhook_event_id\", String(webhook_event_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/deliveries",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "deliveries"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 20 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    },
                    {
                      "key": "agent_id",
                      "value": "{{agent_id}}",
                      "disabled": true
                    },
                    {
                      "key": "status",
                      "value": "failed",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"id\": \"whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5\",\n      \"object\": \"webhook_delivery\",\n      \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n      \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"endpoint_revision\": 1,\n      \"subscription_ids\": [\n        \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\"\n      ],\n      \"state\": \"delivered\",\n      \"revision\": 2,\n      \"cycle\": 1,\n      \"attempts\": 1,\n      \"cycle_attempts\": 1,\n      \"last_http_status\": 204,\n      \"next_attempt_at\": \"2026-10-10T06:30:12.481Z\",\n      \"deadline\": \"2026-10-11T06:30:12.481Z\",\n      \"created_at\": \"2026-10-10T06:30:12.481Z\"\n    },\n    {\n      \"id\": \"whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5\",\n      \"object\": \"webhook_delivery\",\n      \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n      \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"endpoint_revision\": 1,\n      \"subscription_ids\": [\n        \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\"\n      ],\n      \"state\": \"failed\",\n      \"revision\": 2,\n      \"cycle\": 1,\n      \"attempts\": 6,\n      \"cycle_attempts\": 6,\n      \"last_http_status\": 503,\n      \"next_attempt_at\": \"2026-10-10T06:30:12.481Z\",\n      \"deadline\": \"2026-10-11T06:30:12.481Z\",\n      \"created_at\": \"2026-10-10T06:30:12.481Z\",\n      \"last_error\": \"http_error\"\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Get a delivery",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "deliveries",
                "{{webhook_delivery_id}}"
              ]
            },
            "description": "One delivery: its state, latest HTTP status, retry deadline and `revision`."
          },
          "response": [
            {
              "name": "200 — delivered",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "deliveries",
                    "{{webhook_delivery_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5\",\n  \"object\": \"webhook_delivery\",\n  \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"endpoint_revision\": 1,\n  \"subscription_ids\": [\n    \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\"\n  ],\n  \"state\": \"delivered\",\n  \"revision\": 2,\n  \"cycle\": 1,\n  \"attempts\": 1,\n  \"cycle_attempts\": 1,\n  \"last_http_status\": 204,\n  \"next_attempt_at\": \"2026-10-10T06:30:12.481Z\",\n  \"deadline\": \"2026-10-11T06:30:12.481Z\",\n  \"created_at\": \"2026-10-10T06:30:12.481Z\"\n}"
            },
            {
              "name": "200 — failed after retries",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "deliveries",
                    "{{webhook_delivery_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5\",\n  \"object\": \"webhook_delivery\",\n  \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"endpoint_revision\": 1,\n  \"subscription_ids\": [\n    \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\"\n  ],\n  \"state\": \"failed\",\n  \"revision\": 2,\n  \"cycle\": 1,\n  \"attempts\": 6,\n  \"cycle_attempts\": 6,\n  \"last_http_status\": 503,\n  \"next_attempt_at\": \"2026-10-10T06:30:12.481Z\",\n  \"deadline\": \"2026-10-11T06:30:12.481Z\",\n  \"created_at\": \"2026-10-10T06:30:12.481Z\",\n  \"last_error\": \"http_error\"\n}"
            }
          ]
        },
        {
          "name": "List delivery attempts",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}/attempts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "deliveries",
                "{{webhook_delivery_id}}",
                "attempts"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100; 20 when left out",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Every request we made for this delivery, with your server's HTTP status and timing."
          },
          "response": [
            {
              "name": "200 — attempts",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}/attempts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "deliveries",
                    "{{webhook_delivery_id}}",
                    "attempts"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 20 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"number\": 1,\n      \"cycle\": 1,\n      \"started_at\": \"2026-10-10T06:30:12.481Z\",\n      \"ended_at\": \"2026-10-10T06:30:12.623Z\",\n      \"status\": \"delivered\",\n      \"http_status\": 204,\n      \"latency_ms\": 142,\n      \"endpoint_revision\": 1,\n      \"signing_key_version\": 1,\n      \"request_id\": \"req_01K9V2G8J0M2P4R6T8W0Y2A4C6\"\n    }\n  ],\n  \"has_more\": false\n}"
            }
          ]
        },
        {
          "name": "Retry a delivery",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Idempotency-Key",
                "value": "webhook-setup-2026-10-10-01",
                "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}/retry",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "deliveries",
                "{{webhook_delivery_id}}",
                "retry"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": 2,\n  \"use_current_endpoint\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sends a failed delivery again with the same event ID and body; nothing about the call is rerun. `use_current_endpoint: true` uses the destination's current URL and headers instead of the ones it had at the time."
          },
          "response": [
            {
              "name": "202 — queued again",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "deliveries",
                    "{{webhook_delivery_id}}",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 2,\n  \"use_current_endpoint\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5\",\n  \"object\": \"webhook_delivery\",\n  \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n  \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"endpoint_revision\": 1,\n  \"subscription_ids\": [\n    \"whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3\"\n  ],\n  \"state\": \"pending\",\n  \"revision\": 3,\n  \"cycle\": 2,\n  \"attempts\": 6,\n  \"cycle_attempts\": 6,\n  \"last_http_status\": 503,\n  \"next_attempt_at\": \"2026-10-10T06:30:12.481Z\",\n  \"deadline\": \"2026-10-11T06:30:12.481Z\",\n  \"created_at\": \"2026-10-10T06:30:12.481Z\",\n  \"last_error\": \"http_error\"\n}"
            },
            {
              "name": "409 — not failed, or stale revision",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "webhook-setup-2026-10-10-01",
                    "description": "Up to 200 characters. The same key and body return the original answer, including a signing secret, for 30 days."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/deliveries/{{webhook_delivery_id}}/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "deliveries",
                    "{{webhook_delivery_id}}",
                    "retry"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 2,\n  \"use_current_endpoint\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The resource changed since you read it. Read it again, then retry with its revision.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get webhook settings",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/settings",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "settings"
              ]
            },
            "description": "Workspace-wide webhook settings. `low_balance_threshold_inr` is the balance, in rupees, below which `wallet.balance_low` is sent (and above which `wallet.balance_restored` follows a top-up). `call_webhook_urls` lists each `webhook_url` your calls passed in the last 7 days; `endpoint_id` is the destination with the same URL, which now delivers its events."
          },
          "response": [
            {
              "name": "200 — settings",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/settings",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "settings"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"webhook_settings\",\n  \"low_balance_threshold_inr\": 500,\n  \"revision\": 1,\n  \"call_webhook_urls\": [\n    {\n      \"url\": \"https://crm.example.com/mirai/webhooks\",\n      \"last_used_at\": \"2026-10-27T09:16:38Z\",\n      \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"last_status\": \"superseded\",\n      \"failures_24h\": 0\n    },\n    {\n      \"url\": \"https://hooks.example.com/mirai\",\n      \"last_used_at\": \"2026-10-27T09:16:40Z\",\n      \"endpoint_id\": null,\n      \"last_status\": \"failed\",\n      \"last_http_status\": 401,\n      \"last_hint\": \"signature_rejected\",\n      \"failures_24h\": 3\n    }\n  ]\n}"
            },
            {
              "name": "404 — not on this workspace yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/settings",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "settings"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Webhooks are not available on this workspace yet.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Set the low-balance alert level",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/settings",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "settings"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"if_revision\": 1,\n  \"low_balance_threshold_inr\": 1000\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Change the balance that counts as low, in whole rupees (0 to 1,00,00,000). Send the settings' current `revision` as `if_revision`; a stale one is a 409."
          },
          "response": [
            {
              "name": "200 — saved",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/settings",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "settings"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"low_balance_threshold_inr\": 1000\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"webhook_settings\",\n  \"low_balance_threshold_inr\": 1000,\n  \"revision\": 2\n}"
            },
            {
              "name": "409 — stale revision",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/settings",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "settings"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"if_revision\": 1,\n  \"low_balance_threshold_inr\": 1000\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The resource changed since you read it. Read it again, then retry with its revision.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List call webhook_url deliveries",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/webhooks/call-deliveries",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "webhooks",
                "call-deliveries"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100; 50 when left out",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                },
                {
                  "key": "call_id",
                  "value": "{{call_id}}",
                  "description": "only this call's deliveries",
                  "disabled": true
                },
                {
                  "key": "outcome",
                  "value": "failed",
                  "description": "delivered, failed or superseded",
                  "disabled": true
                }
              ]
            },
            "description": "Recent attempts to deliver to the `webhook_url` you pass when creating a call, newest first. Deliveries to destinations are under *List deliveries*. `outcome` is `delivered` (your server answered 2xx), `failed`, or `superseded` (a destination with the same URL delivered the event instead). `signed_with` names the secret that signed it, the same value as `X-Mirai-Signed-With`: `api_key` (your Call webhook secret) or a destination's `whe_…` id. `hint: signature_rejected` means your server answered 401 or 403: verify with the secret `signed_with` names. The newest 500 records are kept, for up to 30 days."
          },
          "response": [
            {
              "name": "200 — recent attempts",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/call-deliveries",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "call-deliveries"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 50 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    },
                    {
                      "key": "call_id",
                      "value": "{{call_id}}",
                      "description": "only this call's deliveries",
                      "disabled": true
                    },
                    {
                      "key": "outcome",
                      "value": "failed",
                      "description": "delivered, failed or superseded",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"id\": \"wcd_01M5Z2Q9S5U7W9Y1A3C5E7G9J1\",\n      \"object\": \"call_webhook_delivery\",\n      \"call_id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\",\n      \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n      \"event_type\": \"call.processing.completed\",\n      \"url\": \"https://crm.example.com/mirai/webhooks\",\n      \"endpoint_id\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"signed_with\": \"whe_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"outcome\": \"superseded\",\n      \"attempt\": 1,\n      \"at\": \"2026-10-27T09:16:41Z\"\n    },\n    {\n      \"id\": \"wcd_01M5Z2Q8R4T6V8X0Z2B4D6F8H0\",\n      \"object\": \"call_webhook_delivery\",\n      \"call_id\": \"call_01K9V1Z9X7V5T3R1P9N7M5K3H1\",\n      \"event_id\": \"evt_01K9V2E6G8J0M2P4R6T8W0Y2A4\",\n      \"event_type\": \"call.completed\",\n      \"url\": \"https://hooks.example.com/mirai\",\n      \"signed_with\": \"api_key\",\n      \"outcome\": \"failed\",\n      \"http_status\": 401,\n      \"hint\": \"signature_rejected\",\n      \"error\": \"http_401\",\n      \"attempt\": 3,\n      \"at\": \"2026-10-27T09:16:40Z\"\n    }\n  ],\n  \"has_more\": false\n}"
            },
            {
              "name": "404 — not on this workspace yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/webhooks/call-deliveries",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "webhooks",
                    "call-deliveries"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100; 50 when left out",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    },
                    {
                      "key": "call_id",
                      "value": "{{call_id}}",
                      "description": "only this call's deliveries",
                      "disabled": true
                    },
                    {
                      "key": "outcome",
                      "value": "failed",
                      "description": "delivered, failed or superseded",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Webhooks are not available on this workspace yet.\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Campaigns",
      "description": "Call a whole list with one agent. Upload contacts, say which days and hours the campaign may ring, and start it. From then on it dials by itself: it paces itself, waits overnight, retries calls that didn't connect, skips numbers on your do-not-call list, and pauses itself when its budget or your wallet runs out, or when as many calls have connected as you asked for.\n\nCampaign calls are ordinary calls. They show up in `GET /v2/calls`, send the same `call.*` webhooks and bill the same per-minute rate. In a sandbox workspace every campaign runs and bills at T5 (₹5 a minute), whatever tier you ask for.\n\nMoney on a campaign is in **paise**: `\"budget_paise\": 50000` is ₹500.\n\nThe requests run top to bottom: create saves `campaign_id`, and the rest use it. Starting a campaign rings every contact on it, so put numbers you're allowed to call in the bodies first.",
      "item": [
        {
          "name": "Create a campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"{{agent_id}}\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"budget_paise\": 50000,\n  \"pause_after_connected\": 50,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"contacts\": [\n    {\n      \"id\": \"lead-1041\",\n      \"phone\": \"{{test_number}}\",\n      \"variables\": {\n        \"name\": \"राहुल\",\n        \"vehicle\": \"स्विफ्ट\",\n        \"due_date\": \"18 अक्टूबर\"\n      },\n      \"metadata\": {\n        \"crm_id\": \"L-1041\",\n        \"branch\": \"Pune\"\n      }\n    },\n    {\n      \"id\": \"lead-1042\",\n      \"phone\": \"+919812345678\",\n      \"variables\": {\n        \"name\": \"प्रिया\",\n        \"vehicle\": \"i20\",\n        \"due_date\": \"20 अक्टूबर\"\n      }\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Makes a **draft** campaign. Nothing rings until you start it.\n\nRequired: `name`, `agent_id`, `timezone`, `start_date`, `end_date` and `slots`. Dates are `YYYY-MM-DD` and slots are `HH:MM`, both in the campaign's own timezone; up to 4 slots, and a slot may cross midnight. Set the dates to the days you actually want to call. A campaign whose dates have passed finishes as soon as it starts.\n\nOptional: `max_concurrent` (1–50, default 1), `retry_count` (0–5 retries after the first attempt, default 0), `re_attempt_period_secs` (60–86400, default 900), `max_duration_secs` (defaults to the agent's), `budget_paise` (leave it out for no cap), `webhook_url`, `skip_called_before` (skip numbers another campaign has already reached), `final_results` (default `true`: each call ends with one `call.processed` carrying the transcript, the results and the contact's metadata), `pause_after_connected` (1–100000: the campaign pauses itself once that many calls have connected; leave it out or send null for no limit), `keyterms` (up to 100 names and words your contacts may say that are easy to mishear; calls listen for them along with the agent's own, and a change reaches the next call, even while the campaign dials) and `tier` (defaults to your plan).\n\n`contacts` is optional here: up to 1000 rows per request, each `{id?, phone, variables?, metadata?}`. `variables` fill the placeholders in the agent's prompt for that person, the same way they do on a single call. `metadata` is your own fields the agent doesn't need (a CRM id, a branch): kept with the contact and sent on each of its calls' webhooks, never given to the agent. Every campaign call's webhooks also name its `campaign_id` and `contact_id`. A bad row doesn't sink the upload. It comes back in `contacts_rejected` with its index, and the good rows are stored.\n\nThere is no idempotency key on this route. If a create times out, list your campaigns before you retry, or you may end up with two."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const campaign_id = pick(\"id\");",
                  "  if (campaign_id != null && campaign_id !== '') pm.collectionVariables.set(\"campaign_id\", String(campaign_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — draft created",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"{{agent_id}}\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"budget_paise\": 50000,\n  \"pause_after_connected\": 50,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"contacts\": [\n    {\n      \"id\": \"lead-1041\",\n      \"phone\": \"{{test_number}}\",\n      \"variables\": {\n        \"name\": \"राहुल\",\n        \"vehicle\": \"स्विफ्ट\",\n        \"due_date\": \"18 अक्टूबर\"\n      },\n      \"metadata\": {\n        \"crm_id\": \"L-1041\",\n        \"branch\": \"Pune\"\n      }\n    },\n    {\n      \"id\": \"lead-1042\",\n      \"phone\": \"+919812345678\",\n      \"variables\": {\n        \"name\": \"प्रिया\",\n        \"vehicle\": \"i20\",\n        \"due_date\": \"20 अक्टूबर\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"draft\",\n  \"pause_reason\": null,\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 50000,\n  \"spent_paise\": 0,\n  \"pause_after_connected\": 50,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-09T06:12:40Z\",\n  \"archived\": false,\n  \"archived_at\": null,\n  \"contacts_accepted\": 2,\n  \"contacts_duplicate\": 0,\n  \"contacts_rejected\": []\n}"
            },
            {
              "name": "400 — end date before start date",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"{{agent_id}}\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"budget_paise\": 50000,\n  \"pause_after_connected\": 50,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"contacts\": [\n    {\n      \"id\": \"lead-1041\",\n      \"phone\": \"{{test_number}}\",\n      \"variables\": {\n        \"name\": \"राहुल\",\n        \"vehicle\": \"स्विफ्ट\",\n        \"due_date\": \"18 अक्टूबर\"\n      },\n      \"metadata\": {\n        \"crm_id\": \"L-1041\",\n        \"branch\": \"Pune\"\n      }\n    },\n    {\n      \"id\": \"lead-1042\",\n      \"phone\": \"+919812345678\",\n      \"variables\": {\n        \"name\": \"प्रिया\",\n        \"vehicle\": \"i20\",\n        \"due_date\": \"20 अक्टूबर\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"end_date 2026-10-10 is before start_date 2026-10-12\"\n  }\n}"
            },
            {
              "name": "404 — no such agent in this workspace",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"{{agent_id}}\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"budget_paise\": 50000,\n  \"pause_after_connected\": 50,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"contacts\": [\n    {\n      \"id\": \"lead-1041\",\n      \"phone\": \"{{test_number}}\",\n      \"variables\": {\n        \"name\": \"राहुल\",\n        \"vehicle\": \"स्विफ्ट\",\n        \"due_date\": \"18 अक्टूबर\"\n      },\n      \"metadata\": {\n        \"crm_id\": \"L-1041\",\n        \"branch\": \"Pune\"\n      }\n    },\n    {\n      \"id\": \"lead-1042\",\n      \"phone\": \"+919812345678\",\n      \"variables\": {\n        \"name\": \"प्रिया\",\n        \"vehicle\": \"i20\",\n        \"due_date\": \"20 अक्टूबर\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"agent agt_01K2M4P7QRSTVWXYZ0A1B9C4 was refused by the dialer: no agent agt_01K2M4P7QRSTVWXYZ0A1B9C4\",\n    \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B9C4\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Add contacts",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "contacts"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"contacts\": [\n    {\n      \"id\": \"lead-1043\",\n      \"phone\": \"+919876501234\",\n      \"variables\": {\n        \"name\": \"अमित\",\n        \"vehicle\": \"नेक्सॉन\",\n        \"due_date\": \"22 अक्टूबर\"\n      }\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Appends up to 1000 contacts per request. Send more requests for a bigger list. A running campaign picks new contacts up straight away.\n\nRows are checked one by one. A phone already in the campaign (or repeated in this batch) counts in `contacts_duplicate`, and a row that can't be stored is listed in `contacts_rejected` with its index in your array. The answer is the campaign object with those three counts on top, the same shape a create returns.\n\nA stopped or completed campaign refuses new contacts (409), since nothing would ever call them."
          },
          "response": [
            {
              "name": "200 — added",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"contacts\": [\n    {\n      \"id\": \"lead-1043\",\n      \"phone\": \"+919876501234\",\n      \"variables\": {\n        \"name\": \"अमित\",\n        \"vehicle\": \"नेक्सॉन\",\n        \"due_date\": \"22 अक्टूबर\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"draft\",\n  \"pause_reason\": null,\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 50000,\n  \"spent_paise\": 0,\n  \"pause_after_connected\": 50,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-09T06:12:40Z\",\n  \"archived\": false,\n  \"archived_at\": null,\n  \"contacts_accepted\": 1,\n  \"contacts_duplicate\": 0,\n  \"contacts_rejected\": []\n}"
            },
            {
              "name": "200 — a repeat and a bad number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"contacts\": [\n    {\n      \"id\": \"lead-1043\",\n      \"phone\": \"+919876501234\",\n      \"variables\": {\n        \"name\": \"अमित\",\n        \"vehicle\": \"नेक्सॉन\",\n        \"due_date\": \"22 अक्टूबर\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"draft\",\n  \"pause_reason\": null,\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 2,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 50000,\n  \"spent_paise\": 0,\n  \"pause_after_connected\": 50,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-09T06:12:40Z\",\n  \"archived\": false,\n  \"archived_at\": null,\n  \"contacts_accepted\": 0,\n  \"contacts_duplicate\": 1,\n  \"contacts_rejected\": [\n    {\n      \"index\": 1,\n      \"phone\": \"98450 12345\",\n      \"reason\": \"phone must be an E.164 number\"\n    }\n  ]\n}"
            },
            {
              "name": "409 — campaign already finished",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"contacts\": [\n    {\n      \"id\": \"lead-1043\",\n      \"phone\": \"+919876501234\",\n      \"variables\": {\n        \"name\": \"अमित\",\n        \"vehicle\": \"नेक्सॉन\",\n        \"due_date\": \"22 अक्टूबर\"\n      }\n    }\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is stopped; it will never dial new contacts\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Remove a contact",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "contacts",
                "{{contact_id}}"
              ]
            },
            "description": "Takes a contact off the list before it has been called, for example a number added by mistake. Set `contact_id` to the id you gave the row.\n\nOnly a contact that has never been dialled can be removed. Once a contact has a call, it's part of the campaign's record. To stop future calls to that number, add it to the do-not-call list instead. Works while the campaign is draft, paused or running. Answers 204 with no body."
          },
          "response": [
            {
              "name": "204 — removed",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}"
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            },
            {
              "name": "409 — it has already been called",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"contact_dialled\",\n    \"message\": \"contact lead-1042 has call history and cannot be removed: only a contact still waiting for its first call can be. To stop future calls to its number, add it to the do-not-call list (POST /v2/dnc)\"\n  }\n}"
            },
            {
              "name": "404 — no such contact",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no contact lead-1042 in campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Cancel a contact",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "contacts",
                "{{contact_id}}",
                "cancel"
              ]
            },
            "description": "Stops calling one contact that's waiting: one not called yet, or one waiting for its next retry after a call nobody picked up. Handy when the reason for the call has gone away, like a cart that turned into an order. Set `contact_id` to the id you gave the row.\n\nThe contact becomes `cancelled` and isn't called again. Its `attempts` and last call stay on the list and in the report, and the campaign no longer waits for it. A call that's already ringing or in conversation is never cut off: you get 409 `contact_in_call`, so try again once it ends. Cancelling twice answers the same contact, so a retried request is safe. Works while the campaign is draft, paused or running. To call a cancelled contact after all, use Call a contact again."
          },
          "response": [
            {
              "name": "200 — cancelled",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/cancel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "cancel"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"lead-1042\",\n  \"phone\": \"+919812345678\",\n  \"status\": \"cancelled\",\n  \"attempts\": 1,\n  \"variables\": {\n    \"name\": \"प्रिया\",\n    \"vehicle\": \"i20\",\n    \"due_date\": \"20 अक्टूबर\"\n  },\n  \"last_call_id\": \"call_01K7D5J7M9P1R3T5V7X9Z1B3D5\",\n  \"last_status\": \"no_answer\",\n  \"eligible_at\": \"2026-10-12T06:15:04.551208Z\",\n  \"updated_at\": \"2026-10-12T06:11:40.203114Z\"\n}"
            },
            {
              "name": "409 — on a call right now",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/cancel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "cancel"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"contact_in_call\",\n    \"message\": \"contact lead-1042 is being called right now, and a call in progress is not cut off; try again after the call ends\"\n  }\n}"
            },
            {
              "name": "409 — already finished",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/cancel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "cancel"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"contact_finished\",\n    \"message\": \"contact lead-1042 has already finished (it is completed) and is not waiting for a call; there is nothing to cancel\"\n  }\n}"
            },
            {
              "name": "404 — no such contact",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/cancel",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "cancel"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no contact lead-1042 in campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Update a campaign",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"budget_paise\": 100000,\n  \"max_concurrent\": 3,\n  \"pause_after_connected\": 100\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Send only the fields you want to change. A draft or paused campaign takes any setting except `agent_id` and `timezone`, which are fixed once it's created. While it's running, only `max_concurrent`, `slots`, `dial_cps`, `agent_revision` and `pause_after_connected` can change, and they take effect straight away. For anything else, pause, edit, then resume.\n\nA campaign keeps the version of its agent it was created with, so a later change to the agent (a new voice, a new prompt) doesn't reach its calls on its own. Send the agent's current `revision` (from `GET /v2/agents/{id}`) as `agent_revision` to move the campaign onto it. A running campaign's next calls use it; calls already in progress finish as they started. It's refused with `agent_inputs_changed` when that version needs variables some waiting contacts don't have.\n\n`pause_after_connected` is the pause rule: the campaign pauses itself, with `pause_reason: connected_limit_reached`, once that many calls have connected (completed, or ran to the max call length; voicemail doesn't count). Turning it on starts the count; changing the number keeps it; `null` removes the rule. Near the limit it rings only as many people as it still needs, and calls in progress always finish.\n\n`\"archived\": true` files a campaign away without touching its status, contacts or report; `false` brings it back. A running campaign can't be archived, and an archived one can't be started until you restore it."
          },
          "response": [
            {
              "name": "200 — updated",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"budget_paise\": 100000,\n  \"max_concurrent\": 3,\n  \"pause_after_connected\": 100\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"draft\",\n  \"pause_reason\": null,\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 3,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 100000,\n  \"spent_paise\": 0,\n  \"pause_after_connected\": 100,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-09T06:15:02Z\",\n  \"archived\": false,\n  \"archived_at\": null\n}"
            },
            {
              "name": "409 — running: pause it first",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"budget_paise\": 100000,\n  \"max_concurrent\": 3,\n  \"pause_after_connected\": 100\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is play; only a draft or paused campaign can be edited — pause it first, or send only max_concurrent, slots, dial_cps, agent_revision or pause_after_connected\"\n  }\n}"
            },
            {
              "name": "400 — out of range",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"budget_paise\": 100000,\n  \"max_concurrent\": 3,\n  \"pause_after_connected\": 100\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"max_concurrent must be between 1 and 50\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Start a campaign",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/start",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "start"
              ]
            },
            "description": "**Dials real people and spends credit.** Every contact on the campaign gets called, so check the numbers first.\n\nWorks on a draft or a paused campaign. A 202 means the campaign is running; it doesn't mean a phone is ringing yet. Outside its calling window it stays `play` and waits for the window to open.\n\nIf your wallet won't cover every remaining contact, the campaign still starts and the answer carries `funded_calls`, a rough count of how many calls the balance pays for. It dials those, then pauses itself with `pause_reason: insufficient_balance`. Top up and start it again to carry on."
          },
          "response": [
            {
              "name": "202 — running",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/start",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "start"
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"status\": \"play\"\n}"
            },
            {
              "name": "202 — running, but the wallet is short",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/start",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "start"
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"status\": \"play\",\n  \"funded_calls\": 1\n}"
            },
            {
              "name": "409 — already running",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/start",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "start"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is already play\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get a campaign",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}"
              ]
            },
            "description": "The campaign's settings, status and `counters`: how many contacts are in each status (`pending`, `dialing`, `completed`, `no_answer`, `busy`, `failed`, `voicemail`, `timeout`, `exhausted`, `suppressed`, `skipped`, `aborted`). Poll it to watch a campaign run.\n\n`status` is `draft`, `play`, `paused`, `stopped` or `completed`. `pause_reason` says why a campaign paused: `insufficient_balance`, `budget_exhausted` or `connected_limit_reached` (its pause rule) when it paused itself, the reason you gave when you did, and null otherwise.\n\nWith a pause rule set, `pause_after_connected_count` is how many calls have connected since `pause_after_connected_since`, when the count began."
          },
          "response": [
            {
              "name": "200 — running",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"play\",\n  \"pause_reason\": null,\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 3,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 100000,\n  \"spent_paise\": 1000,\n  \"pause_after_connected\": 100,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-12T04:32:16Z\",\n  \"counters\": {\n    \"completed\": 1,\n    \"dialing\": 1,\n    \"pending\": 1\n  },\n  \"archived\": false,\n  \"archived_at\": null\n}"
            },
            {
              "name": "200 — paused: the wallet ran out",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"paused\",\n  \"pause_reason\": \"insufficient_balance\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 3,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 100000,\n  \"spent_paise\": 1000,\n  \"pause_after_connected\": 100,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-12T04:36:52Z\",\n  \"counters\": {\n    \"completed\": 2,\n    \"pending\": 1\n  },\n  \"archived\": false,\n  \"archived_at\": null\n}"
            },
            {
              "name": "200 — paused: its pause rule was reached",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"paused\",\n  \"pause_reason\": \"connected_limit_reached\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-10-12\",\n  \"end_date\": \"2026-10-16\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 3,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 100000,\n  \"spent_paise\": 41500,\n  \"pause_after_connected\": 100,\n  \"pause_after_connected_count\": 100,\n  \"pause_after_connected_since\": \"2026-10-12T04:30:00Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-09T06:12:40Z\",\n  \"updated_at\": \"2026-10-13T08:02:11Z\",\n  \"counters\": {\n    \"completed\": 96,\n    \"timeout\": 4,\n    \"no_answer\": 37,\n    \"pending\": 63\n  },\n  \"archived\": false,\n  \"archived_at\": null\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List contacts",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "contacts"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                },
                {
                  "key": "status",
                  "value": "exhausted",
                  "description": "One contact status",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Every contact with where it stands: its `variables` and `metadata`, `status`, `attempts` so far, and `last_call_id`, the call to open with `GET /v2/calls/{id}`. Once a contact has been called, its row also says when (`last_call_at`), for how long (`last_call_secs`), how it ended (`last_call_ended`), the outcome the analysis gave it (`last_call_outcome`) and a short summary.\n\nFilter with `status`, e.g. `exhausted` for everyone who was tried every time and never picked up. Rows come in contact-id order; pass `next_cursor` back as `cursor` for the next page (`limit` 1–100)."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "status",
                      "value": "exhausted",
                      "description": "One contact status",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"lead-1041\",\n      \"phone\": \"+919876543210\",\n      \"status\": \"completed\",\n      \"attempts\": 1,\n      \"variables\": {\n        \"name\": \"राहुल\",\n        \"vehicle\": \"स्विफ्ट\",\n        \"due_date\": \"18 अक्टूबर\"\n      },\n      \"metadata\": {\n        \"crm_id\": \"L-1041\",\n        \"branch\": \"Pune\"\n      },\n      \"last_call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n      \"last_status\": \"completed\",\n      \"eligible_at\": \"2026-10-12T04:30:00.104512Z\",\n      \"updated_at\": \"2026-10-12T04:32:15.482913Z\",\n      \"last_call_at\": \"2026-10-12T04:30:48+00:00\",\n      \"last_call_secs\": 68,\n      \"last_call_outcome\": \"booked\",\n      \"last_call_ended\": \"assistant-ended-call\",\n      \"last_call_summary\": \"ग्राहक ने 18 अक्टूबर सुबह 10 बजे की सर्विस बुक की।\"\n    },\n    {\n      \"id\": \"lead-1042\",\n      \"phone\": \"+919812345678\",\n      \"status\": \"exhausted\",\n      \"attempts\": 2,\n      \"variables\": {\n        \"name\": \"प्रिया\",\n        \"vehicle\": \"i20\",\n        \"due_date\": \"20 अक्टूबर\"\n      },\n      \"last_call_id\": \"call_01K7D5J7M9P1R3T5V7X9Z1B3D5\",\n      \"last_status\": \"no_answer\",\n      \"eligible_at\": \"2026-10-12T05:31:31.218734Z\",\n      \"updated_at\": \"2026-10-12T05:32:40.903117Z\",\n      \"last_call_ended\": \"no-answer\"\n    },\n    {\n      \"id\": \"lead-1043\",\n      \"phone\": \"+919876501234\",\n      \"status\": \"completed\",\n      \"attempts\": 1,\n      \"variables\": {\n        \"name\": \"अमित\",\n        \"vehicle\": \"नेक्सॉन\",\n        \"due_date\": \"22 अक्टूबर\"\n      },\n      \"last_call_id\": \"call_01K7D3G5J7M9P1R3T5V7X9Z1B4\",\n      \"last_status\": \"completed\",\n      \"eligible_at\": \"2026-10-12T04:30:00.104512Z\",\n      \"updated_at\": \"2026-10-12T04:36:51.377260Z\",\n      \"last_call_at\": \"2026-10-12T04:34:18+00:00\",\n      \"last_call_secs\": 44,\n      \"last_call_outcome\": \"will_call_back\",\n      \"last_call_ended\": \"customer-ended-call\",\n      \"last_call_summary\": \"ग्राहक अभी गाड़ी चला रहे थे, शाम को खुद कॉल करेंगे।\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "List campaigns",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20"
                },
                {
                  "key": "archived",
                  "value": "false",
                  "description": "true: archived only. false: active only.",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Your campaigns, newest first, cursor-paged (`limit` 1–100). Pages leave out `counters`; get one campaign for those.\n\nLeave `archived` out to see everything, or send `true` for archived only and `false` for active only. Keep the same filter while you follow `next_cursor`."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20"
                    },
                    {
                      "key": "archived",
                      "value": "false",
                      "description": "true: archived only. false: active only.",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"agent_revision\": 1,\n      \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n      \"object\": \"campaign\",\n      \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"tier\": \"t5\",\n      \"status\": \"completed\",\n      \"pause_reason\": null,\n      \"timezone\": \"Asia/Kolkata\",\n      \"start_date\": \"2026-10-12\",\n      \"end_date\": \"2026-10-16\",\n      \"slots\": [\n        {\n          \"start\": \"10:00\",\n          \"end\": \"13:00\"\n        },\n        {\n          \"start\": \"16:00\",\n          \"end\": \"19:00\"\n        }\n      ],\n      \"max_concurrent\": 3,\n      \"retry_count\": 1,\n      \"re_attempt_period_secs\": 3600,\n      \"max_duration_secs\": 300,\n      \"budget_paise\": 100000,\n      \"spent_paise\": 1500,\n      \"pause_after_connected\": 100,\n      \"skip_called_before\": false,\n      \"keyterms\": [\n        \"सर्विस\",\n        \"नेक्सॉन\"\n      ],\n      \"final_results\": true,\n      \"created_at\": \"2026-10-09T06:12:40Z\",\n      \"updated_at\": \"2026-10-12T05:41:09Z\",\n      \"archived\": false,\n      \"archived_at\": null\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "List campaign groups",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaign-groups",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaign-groups"
              ]
            },
            "description": "Some work runs as more than one campaign, say a first round and a follow-up round to the same list. A group ties those campaigns together so the insights and the CSV of the first one cover all of them, one row per person. Our team sets groups up for you on request; this route tells you which ones exist.\n\n`groups` is keyed by the campaign the report lives on, and `member_of` maps each other campaign back to it. Most workspaces have none, and get empty maps."
          },
          "response": [
            {
              "name": "200 — one group",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaign-groups",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaign-groups"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_group_map\",\n  \"groups\": {\n    \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\": {\n      \"members\": [\n        \"cmp_01K7B0E3R5T7V9X1Z3B5D7F9GH\"\n      ],\n      \"display_name\": \"सर्विस रिमाइंडर — अक्टूबर + नवंबर\"\n    }\n  },\n  \"member_of\": {\n    \"cmp_01K7B0E3R5T7V9X1Z3B5D7F9GH\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            },
            {
              "name": "200 — no groups",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaign-groups",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaign-groups"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_group_map\",\n  \"groups\": {},\n  \"member_of\": {}\n}"
            }
          ]
        },
        {
          "name": "Pause a campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/pause",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "pause"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reason\": \"Diwali week, resume on 27 Oct\",\n  \"by\": \"ritu\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Stops new calls straight away. Calls already in progress aren't cut off. To end one of those, abort the call itself. Only a running campaign can be paused.\n\nThe body is optional. `reason` and `by` (300 characters between them) are saved as `pause_reason`, so whoever looks at the campaign later knows who paused it and why."
          },
          "response": [
            {
              "name": "202 — paused",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/pause",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "pause"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"reason\": \"Diwali week, resume on 27 Oct\",\n  \"by\": \"ritu\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"pause_reason\": \"ritu: Diwali week, resume on 27 Oct\",\n  \"status\": \"paused\"\n}"
            },
            {
              "name": "409 — not running",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/pause",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "pause"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"reason\": \"Diwali week, resume on 27 Oct\",\n  \"by\": \"ritu\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is draft and cannot be paused\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Resume a campaign",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/resume",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "resume"
              ]
            },
            "description": "Picks a paused campaign up where it stopped. **Calls real people and spends credit.** Clears `pause_reason`. After its pause rule paused it (`connected_limit_reached`), the count starts again, so it calls the next batch.\n\nIf resume answers 409 and tells you to start the campaign, do that. Start picks it up the same way and checks your wallet again before it dials."
          },
          "response": [
            {
              "name": "202 — running again",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/resume",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "resume"
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"status\": \"play\"\n}"
            },
            {
              "name": "409 — use start instead",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/resume",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "resume"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN has no running dialer; POST /v2/campaigns/cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN/start to resume it\"\n  }\n}"
            },
            {
              "name": "409 — archived",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/resume",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "resume"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"campaign_archived\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is archived; restore the campaign before resuming it\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get the history",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/history?limit=50",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "history"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50"
                }
              ]
            },
            "description": "Every start, pause, resume, stop, completion and pause-rule change, newest first (`limit` 1–200, default 50), so you can see why a campaign paused after the fact.\n\n`by` is who did it, and null when the campaign did it on its own. Name yourself with a `Mirai-Actor` header on any campaign write (create, update, start, pause, resume, stop); without one it's your API key's label. `reason` is the pause reason on a pause, and on a completion `list_finished` or `end_date`. A pause by the rule adds `pause_after_connected` and `connected`; a rule change adds the new and `previous_pause_after_connected` (null means none); a start or resume adds `count_restarted: true` when the rule's count started again."
          },
          "response": [
            {
              "name": "200 — a paused campaign",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/history?limit=50",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "history"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "50"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"type\": \"paused\",\n      \"at\": \"2026-10-13T08:02:11Z\",\n      \"by\": null,\n      \"reason\": \"connected_limit_reached\",\n      \"pause_after_connected\": 100,\n      \"connected\": 100\n    },\n    {\n      \"type\": \"pause_rule_changed\",\n      \"at\": \"2026-10-12T05:10:40Z\",\n      \"by\": \"ritu\",\n      \"reason\": null,\n      \"pause_after_connected\": 100,\n      \"previous_pause_after_connected\": 50\n    },\n    {\n      \"type\": \"resumed\",\n      \"at\": \"2026-10-12T04:30:00Z\",\n      \"by\": \"ritu\",\n      \"reason\": null\n    },\n    {\n      \"type\": \"paused\",\n      \"at\": \"2026-10-12T04:20:00Z\",\n      \"by\": null,\n      \"reason\": \"insufficient_balance\"\n    },\n    {\n      \"type\": \"started\",\n      \"at\": \"2026-10-12T04:00:03Z\",\n      \"by\": \"ritu\",\n      \"reason\": null\n    }\n  ]\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/history?limit=50",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "history"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "50"
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Call a contact again",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/retry",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "contacts",
                "{{contact_id}}",
                "retry"
              ]
            },
            "description": "Puts one contact back in line for another call, even one that has used up its retries. Useful when someone asks to be called back, or a number was wrong and is now fixed. **On a running campaign it rings as soon as the calling window and pacing allow, and the call spends credit.**\n\nThe contact keeps its history: `attempts` goes up by one when the new call is placed. Works while the campaign is draft, paused or running. A contact that's already waiting or on a call is refused, so a double click doesn't call anyone twice. So is a number on your do-not-call list."
          },
          "response": [
            {
              "name": "200 — back in line",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "retry"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"lead-1042\",\n  \"phone\": \"+919812345678\",\n  \"status\": \"pending\",\n  \"attempts\": 2,\n  \"variables\": {\n    \"name\": \"प्रिया\",\n    \"vehicle\": \"i20\",\n    \"due_date\": \"20 अक्टूबर\"\n  },\n  \"last_call_id\": \"call_01K7D5J7M9P1R3T5V7X9Z1B3D5\",\n  \"last_status\": \"no_answer\",\n  \"eligible_at\": \"2026-10-12T06:10:04.551208Z\",\n  \"updated_at\": \"2026-10-12T06:10:04.551208Z\"\n}"
            },
            {
              "name": "409 — already waiting to be called",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "retry"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"contact_in_progress\",\n    \"message\": \"contact lead-1042 is already waiting to be called\"\n  }\n}"
            },
            {
              "name": "409 — on the do-not-call list",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/contacts/{{contact_id}}/retry",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "contacts",
                    "{{contact_id}}",
                    "retry"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"contact_suppressed\",\n    \"message\": \"contact lead-1042 cannot be called again: its number is on the do-not-call list\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get the report",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/report",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "report"
              ],
              "query": [
                {
                  "key": "format",
                  "value": "csv",
                  "description": "Download the per-contact spreadsheet instead",
                  "disabled": true
                }
              ]
            },
            "description": "The totals: contacts by status, how many were `dialed` at least once, total `attempts` including retries, how many `connected` (completed, voicemail or timeout: the calls you paid for), and the spend.\n\nTurn on `format=csv` for the spreadsheet: one row per contact with your own columns (its id, phone and variables), its status and attempts, then what its last call did: start time, duration, how it ended, cost, outcome, summary, the full transcript and a recording link that works for 7 days. Your variables become columns right after `id`, `phone` and `name`, so the file lines up with the list you uploaded. Read columns by header name."
          },
          "response": [
            {
              "name": "200 — totals",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/report",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "report"
                  ],
                  "query": [
                    {
                      "key": "format",
                      "value": "csv",
                      "description": "Download the per-contact spreadsheet instead",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"status\": \"completed\",\n  \"counters\": {\n    \"completed\": 2,\n    \"exhausted\": 1\n  },\n  \"contacts\": 3,\n  \"dialed\": 3,\n  \"attempts\": 4,\n  \"connected\": 2,\n  \"spent_paise\": 1500,\n  \"spent_inr\": 15,\n  \"budget_paise\": 100000\n}"
            },
            {
              "name": "200 — format=csv",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/report",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "report"
                  ],
                  "query": [
                    {
                      "key": "format",
                      "value": "csv",
                      "description": "Download the per-contact spreadsheet instead",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "text",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/csv; charset=utf-8"
                },
                {
                  "key": "Content-Disposition",
                  "value": "attachment; filename=\"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN.csv\""
                }
              ],
              "cookie": [],
              "body": "id,phone,name,due_date,vehicle,status,attempts,last_call_id,started_at,duration_secs,ended_reason,cost_inr,outcome,success,summary,transcript,recording_url\nlead-1041,+919876543210,राहुल,18 अक्टूबर,स्विफ्ट,completed,1,call_01K2M4RB8CDEFGHJKMNPQRST,2026-10-12T04:30:48Z,68,assistant-ended-call,10.0,booked,yes,ग्राहक ने 18 अक्टूबर सुबह 10 बजे की सर्विस बुक की।,\"bot: नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\nuser: हाँ बोलिए\nbot: आपकी स्विफ्ट की सर्विस 18 अक्टूबर को ड्यू है. स्लॉट बुक कर दूं?\nuser: हाँ, सुबह 10 बजे कर दीजिए\",https://s3.ap-south-1.amazonaws.com/…/call_01K2M4RB8CDEFGHJKMNPQRST.wav?X-Amz-Expires=604800&X-Amz-Signature=…\nlead-1042,+919812345678,प्रिया,20 अक्टूबर,i20,exhausted,2,call_01K7D5J7M9P1R3T5V7X9Z1B3D5,,0,no-answer,,,,,,\nlead-1043,+919876501234,अमित,22 अक्टूबर,नेक्सॉन,completed,1,call_01K7D3G5J7M9P1R3T5V7X9Z1B4,2026-10-12T04:34:18Z,44,customer-ended-call,5.0,will_call_back,no,\"ग्राहक अभी गाड़ी चला रहे थे, शाम को खुद कॉल करेंगे।\",\"bot: नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\nuser: अभी ड्राइव कर रहा हूं, शाम को कॉल करता हूं\",https://s3.ap-south-1.amazonaws.com/…/call_01K7D3G5J7M9P1R3T5V7X9Z1B4.wav?X-Amz-Expires=604800&X-Amz-Signature=…\n"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/report",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "report"
                  ],
                  "query": [
                    {
                      "key": "format",
                      "value": "csv",
                      "description": "Download the per-contact spreadsheet instead",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get insights",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "insights"
              ]
            },
            "description": "The full campaign report as data, the same numbers the console's Insights tab draws:\n\n* `funnel`: from the list you uploaded down to calls that became a real conversation\n* `outcomes`: what the calls ended in, with the bookings and callbacks named\n* `money`: spend taken from your wallet statement, billed minutes, and cost per conversation and per booking\n* `ops`, `quality`, `hygiene`: answer rate by hour, response time, call length, and the numbers on your list that need fixing\n* `cited_calls`: the calls the report quotes, with their transcripts\n\nEach figure has a `tier`. `measured` means counted from the call records; `assumption_based` means it also uses one of the figures in `assumptions` (average ticket size, close rate and so on), which you can change on the Insights tab.\n\nReads are cached until the campaign changes (`meta.served_from_cache`). Building the report costs nothing."
          },
          "response": [
            {
              "name": "200 — the report",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "insights"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_insights\",\n  \"schema\": \"insights.v1.6\",\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"funnel\": {\n    \"tier\": \"measured\",\n    \"stage_order\": [\n      \"list\",\n      \"valid\",\n      \"deduped\",\n      \"dialable\",\n      \"attempted\",\n      \"reached_the_network\",\n      \"connected\",\n      \"conversation\",\n      \"classified\"\n    ],\n    \"stages\": {\n      \"list\": 3,\n      \"valid\": 3,\n      \"deduped\": 3,\n      \"dialable\": 3,\n      \"attempted\": 3,\n      \"reached_the_network\": 3,\n      \"connected\": 2,\n      \"conversation\": 2,\n      \"classified\": 2\n    },\n    \"rates\": {\n      \"answer_rate_pct\": 66.7,\n      \"conversation_rate_pct\": 100.0,\n      \"classified_rate_pct\": 100.0\n    },\n    \"failed_before_media\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"reasons\": {},\n      \"note\": \"dials that never connected audio (a carrier or platform outage), neither an answer nor a rejection\"\n    },\n    \"not_attempted\": {\n      \"value\": 0,\n      \"tier\": \"measured\"\n    },\n    \"connected_without_speech\": {\n      \"value\": 0,\n      \"tier\": \"measured\"\n    },\n    \"retry_effectiveness\": {\n      \"value\": 0.0,\n      \"tier\": \"measured\",\n      \"contacts_retried\": 1,\n      \"answered_after_a_retry\": 0,\n      \"note\": \"attempts is the contact's total; this is 'answered with more than one attempt recorded', not per-attempt history\"\n    }\n  },\n  \"outcomes\": {\n    \"tier\": \"measured\",\n    \"conversations\": 2,\n    \"counts\": {\n      \"booked\": 1,\n      \"will_call_back\": 1\n    },\n    \"percent_of_conversations\": {\n      \"booked\": 50.0,\n      \"will_call_back\": 50.0\n    },\n    \"warm\": {\n      \"value\": 2,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C7\"\n      ],\n      \"definition\": [\n        \"booked\",\n        \"callback_human\",\n        \"will_call_back\"\n      ],\n      \"percent_of_conversations\": 100.0\n    },\n    \"unclassified\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"analysis_not_run\": 0,\n      \"analysis_returned_no_outcome\": 0,\n      \"connected_but_nobody_spoke\": 0,\n      \"never_reached\": 1\n    },\n    \"bookings\": {\n      \"value\": [\n        {\n          \"name\": \"राहुल\",\n          \"phone\": \"+919876543210\",\n          \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n          \"contact_id\": \"lead-1041\",\n          \"summary\": \"ग्राहक ने 18 अक्टूबर सुबह 10 बजे की सर्विस बुक की।\",\n          \"when\": \"18 अक्टूबर, सुबह 10 बजे\"\n        }\n      ],\n      \"tier\": \"measured\"\n    },\n    \"callbacks\": {\n      \"value\": [\n        {\n          \"name\": \"अमित\",\n          \"phone\": \"+919876501234\",\n          \"call_id\": \"call_01K7D3G5J7M9P1R3T5V7X9Z1B4\",\n          \"contact_id\": \"lead-1043\",\n          \"summary\": \"ग्राहक अभी गाड़ी चला रहे थे, शाम को खुद कॉल करेंगे।\",\n          \"when\": \"\"\n        }\n      ],\n      \"tier\": \"measured\"\n    },\n    \"handoffs\": {\n      \"value\": [],\n      \"tier\": \"measured\"\n    },\n    \"label_confidence\": {\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C6\"\n      ],\n      \"value\": null,\n      \"note\": \"outcome labels are AI-classified (±5-10%)\"\n    }\n  },\n  \"money\": {\n    \"tier\": \"measured\",\n    \"source\": \"wallet_ledger\",\n    \"total_spend_inr\": {\n      \"value\": 15.0,\n      \"tier\": \"measured\",\n      \"debit_inr\": 15.0,\n      \"credit_inr\": 0.0,\n      \"calls_charged\": 2,\n      \"calls_without_ledger_line\": 1,\n      \"ledger_truncated\": false,\n      \"scope_note\": \"costs counted are call charges only\"\n    },\n    \"talk_minutes\": {\n      \"value\": 1.87,\n      \"tier\": \"measured\",\n      \"talk_seconds\": 112\n    },\n    \"billed_minutes\": {\n      \"value\": 3,\n      \"tier\": \"measured\",\n      \"charged_calls\": 2,\n      \"calls_under_one_minute\": 1,\n      \"source\": \"wallet_ledger\",\n      \"from_statement\": 2,\n      \"from_rule\": 0,\n      \"rule\": \"per call: ceil(duration / 60), minimum 1\",\n      \"expected_by_rule\": 3,\n      \"matches_rule\": true\n    },\n    \"billed_vs_talk_note\": \"3 minutes were billed against 1.87 minutes of talk time because billing is per call, rounded up, with a one-minute minimum — 1 of the 2 charged calls lasted under a minute.\",\n    \"cost_per_conversation_inr\": {\n      \"value\": 7.5,\n      \"tier\": \"measured\",\n      \"conversations\": 2\n    },\n    \"cost_per_booking_inr\": {\n      \"value\": 15.0,\n      \"tier\": \"measured\",\n      \"bookings\": 1\n    },\n    \"cost_per_warm_inr\": {\n      \"value\": 7.5,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C7\"\n      ],\n      \"warm\": 2\n    },\n    \"cost_per_talk_minute_inr\": {\n      \"value\": 8.02,\n      \"tier\": \"measured\"\n    },\n    \"vs_human\": {\n      \"value\": -0.04,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C4\"\n      ],\n      \"human_cost_inr\": 14.96,\n      \"human_rate_inr_per_min\": 8.0,\n      \"machine_cost_inr\": 15.0\n    },\n    \"expected_pipeline_inr\": {\n      \"value\": 1950.0,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C1\",\n        \"C2\",\n        \"C3\",\n        \"C7\"\n      ],\n      \"bookings\": 1,\n      \"warm\": 2\n    },\n    \"roi_statement\": {\n      \"value\": \"₹15.0 spent → ₹1950.0 expected pipeline\",\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C1\",\n        \"C2\",\n        \"C3\",\n        \"C7\"\n      ]\n    }\n  },\n  \"ops\": {\n    \"tier\": \"measured\",\n    \"calls_without_timestamps\": {\n      \"value\": 1,\n      \"tier\": \"measured\",\n      \"dialled\": 3,\n      \"note\": \"a call record whose start stamp is missing or is a zero value; excluded from the wall clock, the concurrency sweep and the hour histogram\"\n    },\n    \"talk_total_secs\": {\n      \"value\": 112,\n      \"tier\": \"measured\"\n    },\n    \"talk_avg_secs\": {\n      \"value\": 56.0,\n      \"tier\": \"measured\",\n      \"calls\": 2\n    },\n    \"talk_p50_secs\": {\n      \"value\": 44.0,\n      \"tier\": \"measured\"\n    },\n    \"talk_max_secs\": {\n      \"value\": 68,\n      \"tier\": \"measured\"\n    },\n    \"answer_rate_by_hour\": {\n      \"value\": {\n        \"10\": {\n          \"attempted\": 2,\n          \"connected\": 2,\n          \"conversations\": 2,\n          \"answer_rate_pct\": 100.0\n        },\n        \"11\": {\n          \"attempted\": 1,\n          \"connected\": 0,\n          \"conversations\": 0,\n          \"answer_rate_pct\": 0.0\n        }\n      },\n      \"tier\": \"measured\",\n      \"timezone\": \"Asia/Kolkata\",\n      \"timezone_source\": \"zoneinfo\",\n      \"basis\": \"started_at, else created_at (the dial moment)\",\n      \"bucketed_by_created_at\": 1,\n      \"attempts_without_a_timestamp\": 0\n    },\n    \"peak_concurrency_upper_bound\": {\n      \"value\": 1,\n      \"tier\": \"measured\",\n      \"method\": \"sweep over started_at + duration_secs, whole-second stamps\",\n      \"calls_with_a_full_window\": 2,\n      \"calls_missing_a_window\": 1,\n      \"configured_max_concurrent\": 3,\n      \"exceeds_configured\": false\n    },\n    \"wall_clock_secs\": {\n      \"value\": 3664,\n      \"tier\": \"measured\",\n      \"first_call_at\": \"2026-10-12T04:30:48+00:00\",\n      \"last_call_ended_at\": \"2026-10-12T05:31:52+00:00\"\n    }\n  },\n  \"quality\": {\n    \"tier\": \"measured\",\n    \"voice_to_voice_p50_ms\": {\n      \"value\": 790.0,\n      \"tier\": \"measured\",\n      \"calls_measured\": 2,\n      \"calls_unmeasured\": 1,\n      \"sources\": {\n        \"telemetry_v2v\": 2\n      },\n      \"calls_discarded_implausible\": 0,\n      \"floor_ms\": 200.0\n    },\n    \"voice_to_voice_p90_ms\": {\n      \"value\": 820.0,\n      \"tier\": \"measured\",\n      \"calls_measured\": 2\n    },\n    \"turn_end_to_end_p50_ms\": {\n      \"value\": null,\n      \"tier\": \"measured\",\n      \"calls_measured\": 0,\n      \"definition\": \"user stopped speaking -> bot stopped speaking\"\n    },\n    \"turns_per_conversation_avg\": {\n      \"value\": 6.5,\n      \"tier\": \"measured\",\n      \"p50\": 5.0,\n      \"conversations_counted\": 2\n    },\n    \"barge_ins_total\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"calls_with_turn_timing\": 2,\n      \"calls_without_turn_timing\": 1,\n      \"method\": \"transcript_overlap\",\n      \"is_lower_bound\": true,\n      \"definition\": \"a user turn that began before the bot's turn ended\",\n      \"note\": \"a lower bound: an interruption that produced no transcribed user turn is not counted\"\n    },\n    \"short_call_rate_pct\": {\n      \"value\": 0.0,\n      \"tier\": \"measured\",\n      \"threshold_secs\": 15,\n      \"calls\": 0,\n      \"of\": \"conversations\"\n    },\n    \"engaged_rate_pct\": {\n      \"value\": 50.0,\n      \"tier\": \"measured\",\n      \"threshold_secs\": 60,\n      \"calls\": 1,\n      \"of\": \"conversations\"\n    }\n  },\n  \"hygiene\": {\n    \"tier\": \"measured\",\n    \"invalid_numbers\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"reasons\": {},\n      \"rows\": []\n    },\n    \"duplicate_phones\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"extra_rows\": 0,\n      \"rows\": []\n    },\n    \"wrong_numbers\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"rows\": []\n    },\n    \"recently_serviced_contradictions\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"rows\": []\n    },\n    \"unreachable\": {\n      \"value\": 1,\n      \"tier\": \"measured\",\n      \"rows\": [\n        {\n          \"phone\": \"+919812345678\",\n          \"name\": \"प्रिया\",\n          \"attempts\": 2,\n          \"status\": \"exhausted\",\n          \"last_status\": \"no_answer\"\n        }\n      ],\n      \"note\": \"busy / no-answer is not a rejection\"\n    },\n    \"cleanup_value_inr\": {\n      \"value\": 0.0,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C5\"\n      ],\n      \"corrected_records\": 0\n    }\n  },\n  \"deliverables\": {\n    \"tier\": \"measured\",\n    \"csv_url\": \"/v2/campaigns/cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN/report?format=csv\",\n    \"csv_columns\": [\n      \"id\",\n      \"phone\",\n      \"name\",\n      \"due_date\",\n      \"vehicle\",\n      \"status\",\n      \"attempts\",\n      \"last_call_id\",\n      \"started_at\",\n      \"duration_secs\",\n      \"ended_reason\",\n      \"cost_inr\",\n      \"outcome\",\n      \"success\",\n      \"summary\",\n      \"transcript\",\n      \"recording_url\"\n    ],\n    \"csv_variable_columns\": [\n      \"due_date\",\n      \"vehicle\"\n    ],\n    \"recordings\": {\n      \"value\": 2,\n      \"tier\": \"measured\",\n      \"expected\": 2,\n      \"missing\": 0,\n      \"link_expiry_days\": 7,\n      \"basis\": \"call records that name a recording object\"\n    },\n    \"transcripts\": {\n      \"value\": 2,\n      \"tier\": \"measured\",\n      \"expected\": 2,\n      \"missing\": 0\n    },\n    \"call_records\": {\n      \"value\": 3,\n      \"tier\": \"measured\",\n      \"expected\": 3,\n      \"contacts_never_dialled\": 0\n    }\n  },\n  \"cited_calls\": {\n    \"call_01K2M4RB8CDEFGHJKMNPQRST\": {\n      \"name\": \"राहुल\",\n      \"phone_masked\": \"•••••••••3210\",\n      \"outcome\": \"booked\",\n      \"duration_secs\": 68,\n      \"turns\": [\n        {\n          \"role\": \"assistant\",\n          \"text\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\"\n        },\n        {\n          \"role\": \"user\",\n          \"text\": \"हाँ बोलिए\"\n        },\n        {\n          \"role\": \"assistant\",\n          \"text\": \"आपकी स्विफ्ट की सर्विस 18 अक्टूबर को ड्यू है. स्लॉट बुक कर दूं?\"\n        },\n        {\n          \"role\": \"user\",\n          \"text\": \"हाँ, सुबह 10 बजे कर दीजिए\"\n        }\n      ],\n      \"recording\": true\n    },\n    \"call_01K7D3G5J7M9P1R3T5V7X9Z1B4\": {\n      \"name\": \"अमित\",\n      \"phone_masked\": \"•••••••••1234\",\n      \"outcome\": \"will_call_back\",\n      \"duration_secs\": 44,\n      \"turns\": [\n        {\n          \"role\": \"assistant\",\n          \"text\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\"\n        },\n        {\n          \"role\": \"user\",\n          \"text\": \"अभी ड्राइव कर रहा हूं, शाम को कॉल करता हूं\"\n        }\n      ],\n      \"recording\": true\n    }\n  },\n  \"assumptions\": {\n    \"C1\": {\n      \"label\": \"average service ticket\",\n      \"value\": 1500,\n      \"unit\": \"inr\",\n      \"source\": \"default\"\n    },\n    \"C2\": {\n      \"label\": \"warm-lead close rate\",\n      \"value\": 0.3,\n      \"unit\": \"rate\",\n      \"source\": \"default\"\n    },\n    \"C3\": {\n      \"label\": \"booking show-up rate\",\n      \"value\": 0.7,\n      \"unit\": \"rate\",\n      \"source\": \"default\"\n    },\n    \"C4\": {\n      \"label\": \"human telecaller cost\",\n      \"value\": 8,\n      \"unit\": \"inr_per_min\",\n      \"source\": \"default\"\n    },\n    \"C5\": {\n      \"label\": \"value of one corrected CRM record\",\n      \"value\": 10,\n      \"unit\": \"inr\",\n      \"source\": \"default\"\n    },\n    \"C6\": {\n      \"label\": \"outcome labels are AI-classified (±5-10%)\",\n      \"value\": null,\n      \"unit\": \"note\",\n      \"source\": \"default\"\n    },\n    \"C7\": {\n      \"label\": \"warm = booked + will_call_back + callback_human\",\n      \"value\": [\n        \"booked\",\n        \"will_call_back\",\n        \"callback_human\"\n      ],\n      \"unit\": \"outcome_set\",\n      \"source\": \"default\"\n    },\n    \"C8\": {\n      \"label\": \"costs counted are call charges only\",\n      \"value\": null,\n      \"unit\": \"note\",\n      \"source\": \"default\"\n    },\n    \"C9\": {\n      \"label\": \"recording links expire\",\n      \"value\": 7,\n      \"unit\": \"days\",\n      \"source\": \"default\"\n    },\n    \"C10\": {\n      \"label\": \"busy / no-answer is not a rejection\",\n      \"value\": null,\n      \"unit\": \"note\",\n      \"source\": \"default\"\n    }\n  },\n  \"meta\": {\n    \"workspace_id\": \"ws_3f9a1c27d8e4b610\",\n    \"generated_at\": \"2026-10-12T06:02:11Z\",\n    \"data_version\": \"insights.v1.6|2026-10-12T05:41:09Z|completed|1500\",\n    \"campaign\": {\n      \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n      \"status\": \"completed\",\n      \"tier\": \"t5\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"timezone\": \"Asia/Kolkata\",\n      \"created_at\": \"2026-10-09T06:12:40Z\",\n      \"updated_at\": \"2026-10-12T05:41:09Z\"\n    },\n    \"contacts_read\": 3,\n    \"calls_named\": 3,\n    \"call_records_found\": 3,\n    \"call_records_missing\": 0,\n    \"calls_without_timestamps\": 1,\n    \"calls_failed_before_media\": 0,\n    \"contacts_with_multiple_attempts\": 0,\n    \"representative_overrides\": 0,\n    \"attempts_recovered\": 0,\n    \"group\": null,\n    \"cited_calls_carried\": 2,\n    \"cited_calls_truncated\": false,\n    \"cited_calls_max\": 80,\n    \"cited_transcript_chars\": 269,\n    \"ledger_transactions_scanned\": 2,\n    \"ledger_truncated\": false,\n    \"tiers_present\": [\n      \"measured\",\n      \"assumption_based\"\n    ],\n    \"contacts_truncated\": false,\n    \"served_from_cache\": true\n  }\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "insights"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Rebuild insights",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "insights"
              ]
            },
            "description": "Counts the report again from scratch instead of serving the cached one. Call summaries and outcomes can arrive a few minutes after a call ends, so rebuild when the outcome numbers look behind. No body, no charge."
          },
          "response": [
            {
              "name": "200 — freshly counted",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "insights"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_insights\",\n  \"schema\": \"insights.v1.6\",\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"funnel\": {\n    \"tier\": \"measured\",\n    \"stage_order\": [\n      \"list\",\n      \"valid\",\n      \"deduped\",\n      \"dialable\",\n      \"attempted\",\n      \"reached_the_network\",\n      \"connected\",\n      \"conversation\",\n      \"classified\"\n    ],\n    \"stages\": {\n      \"list\": 3,\n      \"valid\": 3,\n      \"deduped\": 3,\n      \"dialable\": 3,\n      \"attempted\": 3,\n      \"reached_the_network\": 3,\n      \"connected\": 2,\n      \"conversation\": 2,\n      \"classified\": 2\n    },\n    \"rates\": {\n      \"answer_rate_pct\": 66.7,\n      \"conversation_rate_pct\": 100.0,\n      \"classified_rate_pct\": 100.0\n    },\n    \"failed_before_media\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"reasons\": {},\n      \"note\": \"dials that never connected audio (a carrier or platform outage), neither an answer nor a rejection\"\n    },\n    \"not_attempted\": {\n      \"value\": 0,\n      \"tier\": \"measured\"\n    },\n    \"connected_without_speech\": {\n      \"value\": 0,\n      \"tier\": \"measured\"\n    },\n    \"retry_effectiveness\": {\n      \"value\": 0.0,\n      \"tier\": \"measured\",\n      \"contacts_retried\": 1,\n      \"answered_after_a_retry\": 0,\n      \"note\": \"attempts is the contact's total; this is 'answered with more than one attempt recorded', not per-attempt history\"\n    }\n  },\n  \"outcomes\": {\n    \"tier\": \"measured\",\n    \"conversations\": 2,\n    \"counts\": {\n      \"booked\": 1,\n      \"will_call_back\": 1\n    },\n    \"percent_of_conversations\": {\n      \"booked\": 50.0,\n      \"will_call_back\": 50.0\n    },\n    \"warm\": {\n      \"value\": 2,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C7\"\n      ],\n      \"definition\": [\n        \"booked\",\n        \"callback_human\",\n        \"will_call_back\"\n      ],\n      \"percent_of_conversations\": 100.0\n    },\n    \"unclassified\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"analysis_not_run\": 0,\n      \"analysis_returned_no_outcome\": 0,\n      \"connected_but_nobody_spoke\": 0,\n      \"never_reached\": 1\n    },\n    \"bookings\": {\n      \"value\": [\n        {\n          \"name\": \"राहुल\",\n          \"phone\": \"+919876543210\",\n          \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n          \"contact_id\": \"lead-1041\",\n          \"summary\": \"ग्राहक ने 18 अक्टूबर सुबह 10 बजे की सर्विस बुक की।\",\n          \"when\": \"18 अक्टूबर, सुबह 10 बजे\"\n        }\n      ],\n      \"tier\": \"measured\"\n    },\n    \"callbacks\": {\n      \"value\": [\n        {\n          \"name\": \"अमित\",\n          \"phone\": \"+919876501234\",\n          \"call_id\": \"call_01K7D3G5J7M9P1R3T5V7X9Z1B4\",\n          \"contact_id\": \"lead-1043\",\n          \"summary\": \"ग्राहक अभी गाड़ी चला रहे थे, शाम को खुद कॉल करेंगे।\",\n          \"when\": \"\"\n        }\n      ],\n      \"tier\": \"measured\"\n    },\n    \"handoffs\": {\n      \"value\": [],\n      \"tier\": \"measured\"\n    },\n    \"label_confidence\": {\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C6\"\n      ],\n      \"value\": null,\n      \"note\": \"outcome labels are AI-classified (±5-10%)\"\n    }\n  },\n  \"money\": {\n    \"tier\": \"measured\",\n    \"source\": \"wallet_ledger\",\n    \"total_spend_inr\": {\n      \"value\": 15.0,\n      \"tier\": \"measured\",\n      \"debit_inr\": 15.0,\n      \"credit_inr\": 0.0,\n      \"calls_charged\": 2,\n      \"calls_without_ledger_line\": 1,\n      \"ledger_truncated\": false,\n      \"scope_note\": \"costs counted are call charges only\"\n    },\n    \"talk_minutes\": {\n      \"value\": 1.87,\n      \"tier\": \"measured\",\n      \"talk_seconds\": 112\n    },\n    \"billed_minutes\": {\n      \"value\": 3,\n      \"tier\": \"measured\",\n      \"charged_calls\": 2,\n      \"calls_under_one_minute\": 1,\n      \"source\": \"wallet_ledger\",\n      \"from_statement\": 2,\n      \"from_rule\": 0,\n      \"rule\": \"per call: ceil(duration / 60), minimum 1\",\n      \"expected_by_rule\": 3,\n      \"matches_rule\": true\n    },\n    \"billed_vs_talk_note\": \"3 minutes were billed against 1.87 minutes of talk time because billing is per call, rounded up, with a one-minute minimum — 1 of the 2 charged calls lasted under a minute.\",\n    \"cost_per_conversation_inr\": {\n      \"value\": 7.5,\n      \"tier\": \"measured\",\n      \"conversations\": 2\n    },\n    \"cost_per_booking_inr\": {\n      \"value\": 15.0,\n      \"tier\": \"measured\",\n      \"bookings\": 1\n    },\n    \"cost_per_warm_inr\": {\n      \"value\": 7.5,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C7\"\n      ],\n      \"warm\": 2\n    },\n    \"cost_per_talk_minute_inr\": {\n      \"value\": 8.02,\n      \"tier\": \"measured\"\n    },\n    \"vs_human\": {\n      \"value\": -0.04,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C4\"\n      ],\n      \"human_cost_inr\": 14.96,\n      \"human_rate_inr_per_min\": 8.0,\n      \"machine_cost_inr\": 15.0\n    },\n    \"expected_pipeline_inr\": {\n      \"value\": 1950.0,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C1\",\n        \"C2\",\n        \"C3\",\n        \"C7\"\n      ],\n      \"bookings\": 1,\n      \"warm\": 2\n    },\n    \"roi_statement\": {\n      \"value\": \"₹15.0 spent → ₹1950.0 expected pipeline\",\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C1\",\n        \"C2\",\n        \"C3\",\n        \"C7\"\n      ]\n    }\n  },\n  \"ops\": {\n    \"tier\": \"measured\",\n    \"calls_without_timestamps\": {\n      \"value\": 1,\n      \"tier\": \"measured\",\n      \"dialled\": 3,\n      \"note\": \"a call record whose start stamp is missing or is a zero value; excluded from the wall clock, the concurrency sweep and the hour histogram\"\n    },\n    \"talk_total_secs\": {\n      \"value\": 112,\n      \"tier\": \"measured\"\n    },\n    \"talk_avg_secs\": {\n      \"value\": 56.0,\n      \"tier\": \"measured\",\n      \"calls\": 2\n    },\n    \"talk_p50_secs\": {\n      \"value\": 44.0,\n      \"tier\": \"measured\"\n    },\n    \"talk_max_secs\": {\n      \"value\": 68,\n      \"tier\": \"measured\"\n    },\n    \"answer_rate_by_hour\": {\n      \"value\": {\n        \"10\": {\n          \"attempted\": 2,\n          \"connected\": 2,\n          \"conversations\": 2,\n          \"answer_rate_pct\": 100.0\n        },\n        \"11\": {\n          \"attempted\": 1,\n          \"connected\": 0,\n          \"conversations\": 0,\n          \"answer_rate_pct\": 0.0\n        }\n      },\n      \"tier\": \"measured\",\n      \"timezone\": \"Asia/Kolkata\",\n      \"timezone_source\": \"zoneinfo\",\n      \"basis\": \"started_at, else created_at (the dial moment)\",\n      \"bucketed_by_created_at\": 1,\n      \"attempts_without_a_timestamp\": 0\n    },\n    \"peak_concurrency_upper_bound\": {\n      \"value\": 1,\n      \"tier\": \"measured\",\n      \"method\": \"sweep over started_at + duration_secs, whole-second stamps\",\n      \"calls_with_a_full_window\": 2,\n      \"calls_missing_a_window\": 1,\n      \"configured_max_concurrent\": 3,\n      \"exceeds_configured\": false\n    },\n    \"wall_clock_secs\": {\n      \"value\": 3664,\n      \"tier\": \"measured\",\n      \"first_call_at\": \"2026-10-12T04:30:48+00:00\",\n      \"last_call_ended_at\": \"2026-10-12T05:31:52+00:00\"\n    }\n  },\n  \"quality\": {\n    \"tier\": \"measured\",\n    \"voice_to_voice_p50_ms\": {\n      \"value\": 790.0,\n      \"tier\": \"measured\",\n      \"calls_measured\": 2,\n      \"calls_unmeasured\": 1,\n      \"sources\": {\n        \"telemetry_v2v\": 2\n      },\n      \"calls_discarded_implausible\": 0,\n      \"floor_ms\": 200.0\n    },\n    \"voice_to_voice_p90_ms\": {\n      \"value\": 820.0,\n      \"tier\": \"measured\",\n      \"calls_measured\": 2\n    },\n    \"turn_end_to_end_p50_ms\": {\n      \"value\": null,\n      \"tier\": \"measured\",\n      \"calls_measured\": 0,\n      \"definition\": \"user stopped speaking -> bot stopped speaking\"\n    },\n    \"turns_per_conversation_avg\": {\n      \"value\": 6.5,\n      \"tier\": \"measured\",\n      \"p50\": 5.0,\n      \"conversations_counted\": 2\n    },\n    \"barge_ins_total\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"calls_with_turn_timing\": 2,\n      \"calls_without_turn_timing\": 1,\n      \"method\": \"transcript_overlap\",\n      \"is_lower_bound\": true,\n      \"definition\": \"a user turn that began before the bot's turn ended\",\n      \"note\": \"a lower bound: an interruption that produced no transcribed user turn is not counted\"\n    },\n    \"short_call_rate_pct\": {\n      \"value\": 0.0,\n      \"tier\": \"measured\",\n      \"threshold_secs\": 15,\n      \"calls\": 0,\n      \"of\": \"conversations\"\n    },\n    \"engaged_rate_pct\": {\n      \"value\": 50.0,\n      \"tier\": \"measured\",\n      \"threshold_secs\": 60,\n      \"calls\": 1,\n      \"of\": \"conversations\"\n    }\n  },\n  \"hygiene\": {\n    \"tier\": \"measured\",\n    \"invalid_numbers\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"reasons\": {},\n      \"rows\": []\n    },\n    \"duplicate_phones\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"extra_rows\": 0,\n      \"rows\": []\n    },\n    \"wrong_numbers\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"rows\": []\n    },\n    \"recently_serviced_contradictions\": {\n      \"value\": 0,\n      \"tier\": \"measured\",\n      \"rows\": []\n    },\n    \"unreachable\": {\n      \"value\": 1,\n      \"tier\": \"measured\",\n      \"rows\": [\n        {\n          \"phone\": \"+919812345678\",\n          \"name\": \"प्रिया\",\n          \"attempts\": 2,\n          \"status\": \"exhausted\",\n          \"last_status\": \"no_answer\"\n        }\n      ],\n      \"note\": \"busy / no-answer is not a rejection\"\n    },\n    \"cleanup_value_inr\": {\n      \"value\": 0.0,\n      \"tier\": \"assumption_based\",\n      \"assumptions_used\": [\n        \"C5\"\n      ],\n      \"corrected_records\": 0\n    }\n  },\n  \"deliverables\": {\n    \"tier\": \"measured\",\n    \"csv_url\": \"/v2/campaigns/cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN/report?format=csv\",\n    \"csv_columns\": [\n      \"id\",\n      \"phone\",\n      \"name\",\n      \"due_date\",\n      \"vehicle\",\n      \"status\",\n      \"attempts\",\n      \"last_call_id\",\n      \"started_at\",\n      \"duration_secs\",\n      \"ended_reason\",\n      \"cost_inr\",\n      \"outcome\",\n      \"success\",\n      \"summary\",\n      \"transcript\",\n      \"recording_url\"\n    ],\n    \"csv_variable_columns\": [\n      \"due_date\",\n      \"vehicle\"\n    ],\n    \"recordings\": {\n      \"value\": 2,\n      \"tier\": \"measured\",\n      \"expected\": 2,\n      \"missing\": 0,\n      \"link_expiry_days\": 7,\n      \"basis\": \"call records that name a recording object\"\n    },\n    \"transcripts\": {\n      \"value\": 2,\n      \"tier\": \"measured\",\n      \"expected\": 2,\n      \"missing\": 0\n    },\n    \"call_records\": {\n      \"value\": 3,\n      \"tier\": \"measured\",\n      \"expected\": 3,\n      \"contacts_never_dialled\": 0\n    }\n  },\n  \"cited_calls\": {\n    \"call_01K2M4RB8CDEFGHJKMNPQRST\": {\n      \"name\": \"राहुल\",\n      \"phone_masked\": \"•••••••••3210\",\n      \"outcome\": \"booked\",\n      \"duration_secs\": 68,\n      \"turns\": [\n        {\n          \"role\": \"assistant\",\n          \"text\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\"\n        },\n        {\n          \"role\": \"user\",\n          \"text\": \"हाँ बोलिए\"\n        },\n        {\n          \"role\": \"assistant\",\n          \"text\": \"आपकी स्विफ्ट की सर्विस 18 अक्टूबर को ड्यू है. स्लॉट बुक कर दूं?\"\n        },\n        {\n          \"role\": \"user\",\n          \"text\": \"हाँ, सुबह 10 बजे कर दीजिए\"\n        }\n      ],\n      \"recording\": true\n    },\n    \"call_01K7D3G5J7M9P1R3T5V7X9Z1B4\": {\n      \"name\": \"अमित\",\n      \"phone_masked\": \"•••••••••1234\",\n      \"outcome\": \"will_call_back\",\n      \"duration_secs\": 44,\n      \"turns\": [\n        {\n          \"role\": \"assistant\",\n          \"text\": \"नमस्ते, मैं आशु बोल रहा हूं मिराई मोटर्स से. एक मिनट है आपके पास?\"\n        },\n        {\n          \"role\": \"user\",\n          \"text\": \"अभी ड्राइव कर रहा हूं, शाम को कॉल करता हूं\"\n        }\n      ],\n      \"recording\": true\n    }\n  },\n  \"assumptions\": {\n    \"C1\": {\n      \"label\": \"average service ticket\",\n      \"value\": 1500,\n      \"unit\": \"inr\",\n      \"source\": \"default\"\n    },\n    \"C2\": {\n      \"label\": \"warm-lead close rate\",\n      \"value\": 0.3,\n      \"unit\": \"rate\",\n      \"source\": \"default\"\n    },\n    \"C3\": {\n      \"label\": \"booking show-up rate\",\n      \"value\": 0.7,\n      \"unit\": \"rate\",\n      \"source\": \"default\"\n    },\n    \"C4\": {\n      \"label\": \"human telecaller cost\",\n      \"value\": 8,\n      \"unit\": \"inr_per_min\",\n      \"source\": \"default\"\n    },\n    \"C5\": {\n      \"label\": \"value of one corrected CRM record\",\n      \"value\": 10,\n      \"unit\": \"inr\",\n      \"source\": \"default\"\n    },\n    \"C6\": {\n      \"label\": \"outcome labels are AI-classified (±5-10%)\",\n      \"value\": null,\n      \"unit\": \"note\",\n      \"source\": \"default\"\n    },\n    \"C7\": {\n      \"label\": \"warm = booked + will_call_back + callback_human\",\n      \"value\": [\n        \"booked\",\n        \"will_call_back\",\n        \"callback_human\"\n      ],\n      \"unit\": \"outcome_set\",\n      \"source\": \"default\"\n    },\n    \"C8\": {\n      \"label\": \"costs counted are call charges only\",\n      \"value\": null,\n      \"unit\": \"note\",\n      \"source\": \"default\"\n    },\n    \"C9\": {\n      \"label\": \"recording links expire\",\n      \"value\": 7,\n      \"unit\": \"days\",\n      \"source\": \"default\"\n    },\n    \"C10\": {\n      \"label\": \"busy / no-answer is not a rejection\",\n      \"value\": null,\n      \"unit\": \"note\",\n      \"source\": \"default\"\n    }\n  },\n  \"meta\": {\n    \"workspace_id\": \"ws_3f9a1c27d8e4b610\",\n    \"generated_at\": \"2026-10-12T06:02:11Z\",\n    \"data_version\": \"insights.v1.6|2026-10-12T05:41:09Z|completed|1500\",\n    \"campaign\": {\n      \"name\": \"सर्विस रिमाइंडर — अक्टूबर\",\n      \"status\": \"completed\",\n      \"tier\": \"t5\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"timezone\": \"Asia/Kolkata\",\n      \"created_at\": \"2026-10-09T06:12:40Z\",\n      \"updated_at\": \"2026-10-12T05:41:09Z\"\n    },\n    \"contacts_read\": 3,\n    \"calls_named\": 3,\n    \"call_records_found\": 3,\n    \"call_records_missing\": 0,\n    \"calls_without_timestamps\": 1,\n    \"calls_failed_before_media\": 0,\n    \"contacts_with_multiple_attempts\": 0,\n    \"representative_overrides\": 0,\n    \"attempts_recovered\": 0,\n    \"group\": null,\n    \"cited_calls_carried\": 2,\n    \"cited_calls_truncated\": false,\n    \"cited_calls_max\": 80,\n    \"cited_transcript_chars\": 269,\n    \"ledger_transactions_scanned\": 2,\n    \"ledger_truncated\": false,\n    \"tiers_present\": [\n      \"measured\",\n      \"assumption_based\"\n    ],\n    \"contacts_truncated\": false,\n    \"served_from_cache\": false\n  }\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "insights"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Open the report page",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights.html",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "insights.html"
              ]
            },
            "description": "The same report as a finished page you can save, print or turn into a PDF. Postman shows it in the Preview tab.\n\nThe CSV and call-audio links inside the page need your API key too, so they won't open for someone you email the file to. To let someone without a key read the report, create a share link."
          },
          "response": [
            {
              "name": "200 — the page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights.html",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "insights.html"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "html",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/html; charset=utf-8"
                }
              ],
              "cookie": [],
              "body": "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta name=\"robots\" content=\"noindex, nofollow\">…<title>सर्विस रिमाइंडर — अक्टूबर — campaign report</title>…</head><body><nav class=\"rail\" aria-label=\"Sections\">…<a href=\"#sec-cover\" data-sec=\"sec-cover\" class=\"on\" aria-current=\"true\"><span class=\"rn tnum\">01</span><span class=\"rt\">Cover</span></a><a href=\"#sec-funnel\" data-sec=\"sec-funnel\"><span class=\"rn tnum\">02</span><span class=\"rt\">Funnel</span></a>…</body></html>"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/insights.html",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "insights.html"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Play a call from the report",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/calls/{{call_id}}/audio",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "calls",
                "{{call_id}}",
                "audio"
              ]
            },
            "description": "A **302** to a signed link for the recording of one call the report quotes (any key of the insights' `cited_calls`). The link works for 7 days. Read the insights at least once first, because only calls the report cites can be played here. For any other call, use `GET /v2/calls/{id}/recording`.\n\nTurn off *Settings → Automatically follow redirects* to see the `Location` header instead of downloading the audio."
          },
          "response": [
            {
              "name": "302 — follow the Location header",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/calls/{{call_id}}/audio",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "calls",
                    "{{call_id}}",
                    "audio"
                  ]
                }
              },
              "status": "Found",
              "code": 302,
              "_postman_previewlanguage": "text",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "text/plain; charset=utf-8"
                },
                {
                  "key": "Location",
                  "value": "https://s3.ap-south-1.amazonaws.com/…/call_01K2M4RB8CDEFGHJKMNPQRST.wav?X-Amz-Expires=604800&X-Amz-Signature=…"
                }
              ],
              "cookie": [],
              "body": "302: Found"
            },
            {
              "name": "404 — not a call this report cites",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/calls/{{call_id}}/audio",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "calls",
                    "{{call_id}}",
                    "audio"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"No such call in this report.\"\n  }\n}"
            },
            {
              "name": "404 — no recording kept",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/calls/{{call_id}}/audio",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "calls",
                    "{{call_id}}",
                    "audio"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"No recording was stored for this call.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Share the report",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "share"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"include_audio\": false,\n  \"interactive\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates a link anyone can open, without signing in or a key, to read this campaign's report for 30 days. The shared page has no CSV download and no recording links.\n\nBoth options are off unless you turn them on: `include_audio` lets readers play the calls the report quotes, and `interactive` adds the what-if controls. Each campaign has one link. Sharing again keeps the same URL, applies the options you send and restarts the 30 days."
          },
          "response": [
            {
              "name": "200 — link ready",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "share"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"include_audio\": false,\n  \"interactive\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_share\",\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"url\": \"https://sandbox.voice.miraiminds.co/r/ciwTr_cFjhSRoJxggUeD832HwbQ5AOg0\",\n  \"include_audio\": false,\n  \"interactive\": false,\n  \"expires_at\": \"2026-11-11T06:05:12Z\"\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "share"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"include_audio\": false,\n  \"interactive\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get the share link",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "share"
              ]
            },
            "description": "The live share link and its options, if the report has been shared. Reading it never creates one."
          },
          "response": [
            {
              "name": "200 — shared",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "share"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_share\",\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"shared\": true,\n  \"url\": \"https://sandbox.voice.miraiminds.co/r/ciwTr_cFjhSRoJxggUeD832HwbQ5AOg0\",\n  \"include_audio\": false,\n  \"interactive\": false,\n  \"expires_at\": \"2026-11-11T06:05:12Z\"\n}"
            },
            {
              "name": "200 — not shared",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "share"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_share\",\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"shared\": false\n}"
            }
          ]
        },
        {
          "name": "Revoke the share link",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "share"
              ]
            },
            "description": "Turns the share link off. Anyone who opens it from now on sees that the link has been revoked. Sharing again later makes a new URL."
          },
          "response": [
            {
              "name": "200 — revoked",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/share",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "share"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"campaign_share\",\n  \"campaign_id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"revoked\": true\n}"
            }
          ]
        },
        {
          "name": "Check how well it hears",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "stt-accuracy"
              ]
            },
            "description": "How well the campaign's agent hears its callers, and the words it keeps getting wrong. Every day we take up to `method.daily_cap` answered calls, compare what the agent heard with our offline transcript of the same recording, and count the words it got wrong.\n\n* `status`: `off` (calls aren't checked), `measuring` (the first check hasn't finished), `not_enough_calls` or `ready`\n* `summary`: the word error rate at the start (`first_wer`) and now (`latest_wer`), as a fraction; 1 minus it is the share of caller words heard right. `keyterm_recall` is how often your words to catch were heard right, or null before you have any\n* `daily`: one row per day that had checked calls (days without any are left out), up to 180 days\n* `keyterm_events`: every word added or removed (`at` in India time), and whether you, a suggestion or Keep learning did it\n* `misheard`: the words it gets wrong, what it heard instead, and calls to listen to\n* `suggestions`: the ones worth adding, with the evidence. `term` is how your agent's transcript writes the word when it hears it right; `spellings` lists every way of writing it, `term` first\n\n`status: off` can still carry the numbers from before checking was switched off. `method.since`, `first_wer`, `latest_wer` and `keyterm_recall` are null until there is something to put in them.\n\nIt's a machine check, not a person listening, so read it as a trend."
          },
          "response": [
            {
              "name": "200 — a week of checks",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"status\": \"ready\",\n  \"method\": {\n    \"reference\": \"offline\",\n    \"calls_scored\": 120,\n    \"since\": \"2026-11-02\",\n    \"daily_cap\": 20\n  },\n  \"summary\": {\n    \"first_wer\": 0.31,\n    \"latest_wer\": 0.18,\n    \"calls_scored\": 120,\n    \"ref_words\": 14400,\n    \"keyterm_recall\": 0.92\n  },\n  \"daily\": [\n    {\n      \"date\": \"2026-11-02\",\n      \"calls\": 20,\n      \"ref_words\": 2400,\n      \"wer\": 0.31,\n      \"keyterm_recall\": null\n    },\n    {\n      \"date\": \"2026-11-03\",\n      \"calls\": 20,\n      \"ref_words\": 2380,\n      \"wer\": 0.29,\n      \"keyterm_recall\": null\n    },\n    {\n      \"date\": \"2026-11-04\",\n      \"calls\": 20,\n      \"ref_words\": 2410,\n      \"wer\": 0.28,\n      \"keyterm_recall\": null\n    },\n    {\n      \"date\": \"2026-11-05\",\n      \"calls\": 20,\n      \"ref_words\": 2420,\n      \"wer\": 0.24,\n      \"keyterm_recall\": 0.81\n    },\n    {\n      \"date\": \"2026-11-06\",\n      \"calls\": 20,\n      \"ref_words\": 2390,\n      \"wer\": 0.2,\n      \"keyterm_recall\": 0.9\n    },\n    {\n      \"date\": \"2026-11-07\",\n      \"calls\": 20,\n      \"ref_words\": 2400,\n      \"wer\": 0.18,\n      \"keyterm_recall\": 0.92\n    }\n  ],\n  \"keyterm_events\": [\n    {\n      \"at\": \"2026-11-05T10:00:00+05:30\",\n      \"term\": \"मिराई मोटर्स\",\n      \"action\": \"add\",\n      \"source\": \"suggestion\",\n      \"scope\": \"campaign\"\n    },\n    {\n      \"at\": \"2026-11-06T02:30:00+05:30\",\n      \"term\": \"स्विफ्ट\",\n      \"action\": \"add\",\n      \"source\": \"auto\",\n      \"scope\": \"campaign\"\n    }\n  ],\n  \"misheard\": [\n    {\n      \"term\": \"नेक्सॉन\",\n      \"heard_as\": [\n        {\n          \"text\": \"नेक्स ऑन\",\n          \"count\": 9\n        },\n        {\n          \"text\": \"नक्शा\",\n          \"count\": 3\n        }\n      ],\n      \"calls\": 7,\n      \"count\": 12,\n      \"in_keyterms\": false,\n      \"example_call_ids\": [\n        \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n        \"call_01K7D5J7M9P1R3T5V7X9Z1B3E6\"\n      ]\n    },\n    {\n      \"term\": \"स्विफ्ट\",\n      \"heard_as\": [\n        {\n          \"text\": \"सिफ्ट\",\n          \"count\": 2\n        }\n      ],\n      \"calls\": 2,\n      \"count\": 2,\n      \"in_keyterms\": true,\n      \"example_call_ids\": [\n        \"call_01K7D5J7M9P1R3T5V7X9Z1B3F7\"\n      ]\n    }\n  ],\n  \"suggestions\": [\n    {\n      \"term\": \"नेक्सॉन\",\n      \"reason\": \"misheard in 7 of 20 calls\",\n      \"confidence\": 0.86,\n      \"calls\": 7,\n      \"heard_as\": [\n        \"नेक्स ऑन\",\n        \"नक्शा\"\n      ],\n      \"spellings\": [\n        \"नेक्सॉन\",\n        \"Nexon\"\n      ]\n    }\n  ],\n  \"auto_learn\": true\n}"
            },
            {
              "name": "200 — first check not done yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"status\": \"measuring\",\n  \"method\": {\n    \"reference\": \"offline\",\n    \"calls_scored\": 0,\n    \"since\": \"2026-11-02\",\n    \"daily_cap\": 20\n  },\n  \"summary\": {\n    \"first_wer\": null,\n    \"latest_wer\": null,\n    \"calls_scored\": 0,\n    \"ref_words\": 0,\n    \"keyterm_recall\": null\n  },\n  \"daily\": [],\n  \"keyterm_events\": [],\n  \"misheard\": [],\n  \"suggestions\": [],\n  \"auto_learn\": false\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Add a suggested word",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy/suggestions/accept",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "stt-accuracy",
                "suggestions",
                "accept"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"term\": \"नेक्सॉन\",\n  \"scope\": \"campaign\",\n  \"spellings\": [\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Adds one of the suggestions to the campaign's words to catch (`keyterms`), with all its `spellings` (up to 10). The agent listens for it from the campaign's next call; nothing about the agent changes. It shows up in `keyterm_events` with `source: suggestion`. `added: false` means it was already on the list; `keyterms` is the whole list after the change.\n\nTo let the campaign add strong suggestions by itself, send `{\"keyterms_auto_learn\": true}` to `PATCH /v2/campaigns/{id}`."
          },
          "response": [
            {
              "name": "200 — added",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy/suggestions/accept",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy",
                    "suggestions",
                    "accept"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"term\": \"नेक्सॉन\",\n  \"scope\": \"campaign\",\n  \"spellings\": [\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"term\": \"नेक्सॉन\",\n  \"added\": true,\n  \"scope\": \"campaign\",\n  \"keyterms\": [\n    \"स्विफ्ट\",\n    \"मिराई मोटर्स\",\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}"
            },
            {
              "name": "200 — already on the list",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy/suggestions/accept",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy",
                    "suggestions",
                    "accept"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"term\": \"नेक्सॉन\",\n  \"scope\": \"campaign\",\n  \"spellings\": [\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"term\": \"नेक्सॉन\",\n  \"added\": false,\n  \"scope\": \"campaign\",\n  \"keyterms\": [\n    \"स्विफ्ट\",\n    \"मिराई मोटर्स\",\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}"
            },
            {
              "name": "409 — the list is full",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy/suggestions/accept",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy",
                    "suggestions",
                    "accept"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"term\": \"नेक्सॉन\",\n  \"scope\": \"campaign\",\n  \"spellings\": [\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"keyterms_full\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN already has the most keyterms a campaign can have (100); remove one with PATCH /v2/campaigns/cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN first\"\n  }\n}"
            },
            {
              "name": "409 — campaign finished",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy/suggestions/accept",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy",
                    "suggestions",
                    "accept"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"term\": \"नेक्सॉन\",\n  \"scope\": \"campaign\",\n  \"spellings\": [\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"campaign_finished\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is completed; its keyterms can no longer change\"\n  }\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stt-accuracy/suggestions/accept",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stt-accuracy",
                    "suggestions",
                    "accept"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"term\": \"नेक्सॉन\",\n  \"scope\": \"campaign\",\n  \"spellings\": [\n    \"नेक्सॉन\",\n    \"Nexon\"\n  ]\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Stop a campaign",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stop",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "stop"
              ]
            },
            "description": "Ends the campaign for good. Live calls are hung up, contacts still waiting are marked `aborted`, and it never dials again. Its report stays. Works from draft, running or paused.\n\nTo carry on later, pause instead. To run the same list again, duplicate it."
          },
          "response": [
            {
              "name": "202 — stopped",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stop",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stop"
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\",\n  \"status\": \"stopped\"\n}"
            },
            {
              "name": "409 — already finished",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/stop",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "stop"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN is completed and cannot be stopped\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Duplicate a campaign",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/duplicate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "campaigns",
                "{{campaign_id}}",
                "duplicate"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — नवंबर\",\n  \"start_date\": \"2026-11-09\",\n  \"end_date\": \"2026-11-13\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Copies a campaign's settings and its whole contact list into a new draft, ready to edit and start. Every contact comes over fresh, as never called, with the same id, phone, variables and metadata. Finished and archived campaigns can be copied too.\n\nThe body is optional and takes any create field except `contacts`. What you send replaces the original's value; the name defaults to the original's plus \" (copy)\", and the dates stay the same unless you send new ones. The copy has to pass the same checks as a create, so its agent must still exist and not be archived.\n\nThe new campaign's id is saved as `campaign_id`, so the requests above now work on the copy."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const campaign_id = pick(\"id\");",
                  "  if (campaign_id != null && campaign_id !== '') pm.collectionVariables.set(\"campaign_id\", String(campaign_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — copy created",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/duplicate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "duplicate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — नवंबर\",\n  \"start_date\": \"2026-11-09\",\n  \"end_date\": \"2026-11-13\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"agent_revision\": 1,\n  \"id\": \"cmp_01K7B0E3R5T7V9X1Z3B5D7F9GH\",\n  \"object\": \"campaign\",\n  \"name\": \"सर्विस रिमाइंडर — नवंबर\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"tier\": \"t5\",\n  \"status\": \"draft\",\n  \"pause_reason\": null,\n  \"timezone\": \"Asia/Kolkata\",\n  \"start_date\": \"2026-11-09\",\n  \"end_date\": \"2026-11-13\",\n  \"slots\": [\n    {\n      \"start\": \"10:00\",\n      \"end\": \"13:00\"\n    },\n    {\n      \"start\": \"16:00\",\n      \"end\": \"19:00\"\n    }\n  ],\n  \"max_concurrent\": 3,\n  \"retry_count\": 1,\n  \"re_attempt_period_secs\": 3600,\n  \"max_duration_secs\": 300,\n  \"budget_paise\": 100000,\n  \"spent_paise\": 0,\n  \"pause_after_connected\": 100,\n  \"pause_after_connected_count\": 0,\n  \"pause_after_connected_since\": \"2026-10-09T06:12:40Z\",\n  \"skip_called_before\": false,\n  \"keyterms\": [\n    \"सर्विस\",\n    \"नेक्सॉन\"\n  ],\n  \"final_results\": true,\n  \"created_at\": \"2026-10-16T09:20:31Z\",\n  \"updated_at\": \"2026-10-16T09:20:31Z\",\n  \"archived\": false,\n  \"archived_at\": null,\n  \"contacts_accepted\": 3,\n  \"contacts_duplicate\": 0,\n  \"contacts_rejected\": [],\n  \"duplicated_from\": \"cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n}"
            },
            {
              "name": "400 — contacts sent",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/duplicate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "duplicate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — नवंबर\",\n  \"start_date\": \"2026-11-09\",\n  \"end_date\": \"2026-11-13\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"contacts cannot be sent when duplicating: the source campaign's whole contact list is copied; add more with POST /v2/campaigns/{id}/contacts on the copy\"\n  }\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/campaigns/{{campaign_id}}/duplicate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "campaigns",
                    "{{campaign_id}}",
                    "duplicate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"सर्विस रिमाइंडर — नवंबर\",\n  \"start_date\": \"2026-11-09\",\n  \"end_date\": \"2026-11-13\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no campaign cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Do-not-call list",
      "description": "Numbers your campaigns will never dial. The list covers every campaign in the workspace, including ones that are already running: it's checked at the moment a contact is about to be called, so a number added mid-campaign is skipped from then on. A skipped contact stays in its campaign as `suppressed` and costs nothing.\n\nIt doesn't apply to single calls placed with `POST /v2/calls`; check the list yourself before those if you need to. It's your own list, not the national DND register, and adding a number here doesn't meet your DND obligations.",
      "item": [
        {
          "name": "Add a number",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/dnc",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "dnc"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"+919812345678\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Adds one number in E.164 (`+919812345678`, not `9812345678`). Adding a number that's already there isn't an error: you get 200 with `\"added\": false` instead of 201. Either way the number won't be called, so it's safe to send on every opt-out without checking first."
          },
          "response": [
            {
              "name": "201 — added",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/dnc",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "dnc"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"+919812345678\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"dnc_entry\",\n  \"phone\": \"+919812345678\",\n  \"added\": true\n}"
            },
            {
              "name": "200 — already on the list",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/dnc",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "dnc"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"+919812345678\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"dnc_entry\",\n  \"phone\": \"+919812345678\",\n  \"added\": false\n}"
            },
            {
              "name": "400 — not an E.164 number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/dnc",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "dnc"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"+919812345678\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"phone must be an E.164 phone number, got '9812345678'\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List numbers",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/dnc?limit=100",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "dnc"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "100"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page, URL-encoded",
                  "disabled": true
                }
              ]
            },
            "description": "Every number on the list, in number order, with when it was added. `limit` is 1–100 (default 20); when `has_more` is true, pass `next_cursor` back as `cursor`. The cursor is a phone number, so URL-encode it (`+` becomes `%2B`)."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/dnc?limit=100",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "dnc"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "100"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page, URL-encoded",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"object\": \"dnc_entry\",\n      \"phone\": \"+919812345678\",\n      \"created_at\": \"2026-10-12T06:20:44Z\"\n    },\n    {\n      \"object\": \"dnc_entry\",\n      \"phone\": \"+919845012345\",\n      \"created_at\": \"2026-10-03T11:02:19Z\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Remove a number",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/dnc/{{dnc_phone}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "dnc",
                "{{dnc_phone}}"
              ]
            },
            "description": "Takes a number off the list, and campaigns may call it again from this moment. Contacts already marked `suppressed` stay that way.\n\nThe number goes in the path with `+` written as `%2B`; `dnc_phone` is `%2B919812345678`. Answers 204 with no body, or 404 if the number wasn't on the list. Keep a note of who removed a number and why, since a reversed opt-out is exactly what a complaint will ask about."
          },
          "response": [
            {
              "name": "204 — removed",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/dnc/{{dnc_phone}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "dnc",
                    "{{dnc_phone}}"
                  ]
                }
              },
              "status": "No Content",
              "code": 204,
              "_postman_previewlanguage": "text",
              "header": [],
              "cookie": [],
              "body": ""
            },
            {
              "name": "404 — not on the list",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/dnc/{{dnc_phone}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "dnc",
                    "{{dnc_phone}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"+919812345678 is not on the do-not-call list\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Phone numbers",
      "description": "The numbers your agents answer. Each one comes from the **Telephony** folder:\n\n* **Rented from Mirai.** Once the rental is active, the number shows up here by itself (`ownership: managed`).\n* **From your own Plivo account.** Connect the account in Telephony, list its numbers, then bring one here with *Import a Plivo number* (`ownership: customer`). Plivo keeps billing you for it.\n* **On your own SIP trunk.** Connect the trunk in Telephony, then add each of its numbers with *Add a number on your SIP trunk* (`provider: sip`). It arrives `ready`: assign an agent and it answers.\n\nAfter that it's two steps, in this order: *Assign an agent* (who answers), then *Turn on incoming calls*. `state` is `imported` until calls are on and `ready` after; `error` means the last attempt to turn calls on failed, and `setup_error` says why.\n\nEvery change sends the number's current `version`, and each change raises it by one. If you're not sure what it is, read the number first; a stale version is a 409 `conflict` and changes nothing.\n\nTo call out from one of your numbers, place a call with `phone_number_id` set to its id once it is `ready` (Indian destinations only). Calls on your numbers are billed like any other call.\n\nEvery number also says how it is doing in `health`: `state` is `active`, `warming` (its first week, at half its pool's pace), `resting`, `cooling` (rested three times in a day; waits for you) or `retired`, with this hour's attempts and seven days of answers. You can rest, resume and retire your own numbers; a resting or retired number still answers calls to it.",
      "item": [
        {
          "name": "Import a Plivo number",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"connection_id\": \"{{connection_id}}\",\n  \"number\": \"{{plivo_number}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Brings a number your connected Plivo account already owns into this workspace. It doesn't buy anything or change the number in Plivo yet.\n\n`connection_id` is the connection from *Connect your Plivo account*, and `number` is one of the E.164 numbers *List numbers in your Plivo account* returned (India, `+91`, voice-enabled). Importing the same number again returns the one you already have.\n\nNumbers you rent from Mirai are added for you; don't import those."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const phone_number_id = pick(\"id\");",
                  "  if (phone_number_id != null && phone_number_id !== '') pm.collectionVariables.set(\"phone_number_id\", String(phone_number_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — imported",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"connection_id\": \"{{connection_id}}\",\n  \"number\": \"{{plivo_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"\",\n  \"state\": \"imported\",\n  \"connection_state\": \"verified\",\n  \"version\": 1,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\"\n}"
            },
            {
              "name": "404 — that account doesn't own the number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"connection_id\": \"{{connection_id}}\",\n  \"number\": \"{{plivo_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            },
            {
              "name": "409 — the connection is disabled",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"connection_id\": \"{{connection_id}}\",\n  \"number\": \"{{plivo_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_ready\",\n    \"message\": \"Verify the connection and activate the number before calling\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Add a number on your SIP trunk",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"connection_id\": \"{{sip_connection_id}}\",\n  \"number\": \"+918045671234\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Adds a number your carrier sends to your SIP trunk. A trunk has no number list, so you name the number: an Indian number, `+91` and 10 digits. `connection_id` is the trunk from *Telephony → Connect your SIP trunk*.\n\nThere is nothing to turn on at a provider: the number is `ready` at once. Assign an agent and calls to it are answered; *Turn on incoming calls* on it changes nothing. A number can be in one workspace only, so a number already on Mirai is a 409."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const phone_number_id = pick(\"id\");",
                  "  if (phone_number_id != null && phone_number_id !== '') pm.collectionVariables.set(\"phone_number_id\", String(phone_number_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — added, ready",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"connection_id\": \"{{sip_connection_id}}\",\n  \"number\": \"+918045671234\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9S4Y7F0H5K8M1NQRSTVWXYZ\",\n  \"connection_id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"provider\": \"sip\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918045671234\",\n  \"agent_id\": \"\",\n  \"state\": \"ready\",\n  \"connection_state\": \"verified\",\n  \"version\": 1,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-11-02T09:20:31.402117Z\"\n}"
            },
            {
              "name": "400 — not an Indian number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"connection_id\": \"{{sip_connection_id}}\",\n  \"number\": \"+918045671234\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"number must be +91 followed by 10 digits\"\n  }\n}"
            },
            {
              "name": "409 — already on Mirai",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"connection_id\": \"{{sip_connection_id}}\",\n  \"number\": \"+918045671234\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The number/account is already connected or the configuration version changed; refresh before retrying\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List phone numbers",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "phn_01K9Q3A7C2E4G6J8M0P2R4T6V8",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Every number in the workspace, rented and imported, with the agent each one is assigned to. Up to 100 per page; pass `next_cursor` back as `cursor` while `has_more` is true."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers"
                  ],
                  "query": [
                    {
                      "key": "cursor",
                      "value": "phn_01K9Q3A7C2E4G6J8M0P2R4T6V8",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n      \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"customer\",\n      \"number\": \"+918048123456\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"state\": \"ready\",\n      \"connection_state\": \"verified\",\n      \"version\": 3,\n      \"webhook_url\": \"\",\n      \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n      \"health\": {\n        \"state\": \"active\",\n        \"resting_until\": null,\n        \"cooling_until\": null,\n        \"retired_at\": null,\n        \"warming\": null,\n        \"attempts_this_hour\": 12,\n        \"attempts_today\": 24,\n        \"answers_today\": 17,\n        \"answer_rate_7d\": 0.6955,\n        \"series_7d\": [\n          {\n            \"day\": \"2026-10-09\",\n            \"attempts\": 52,\n            \"answers\": 31\n          },\n          {\n            \"day\": \"2026-10-10\",\n            \"attempts\": 60,\n            \"answers\": 39\n          },\n          {\n            \"day\": \"2026-10-11\",\n            \"attempts\": 0,\n            \"answers\": 0\n          },\n          {\n            \"day\": \"2026-10-12\",\n            \"attempts\": 58,\n            \"answers\": 41\n          },\n          {\n            \"day\": \"2026-10-13\",\n            \"attempts\": 61,\n            \"answers\": 40\n          },\n          {\n            \"day\": \"2026-10-14\",\n            \"attempts\": 59,\n            \"answers\": 43\n          },\n          {\n            \"day\": \"2026-10-15\",\n            \"attempts\": 24,\n            \"answers\": 17\n          }\n        ],\n        \"rests_today\": 0\n      },\n      \"pools\": [\n        {\n          \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n          \"name\": \"Outreach\"\n        }\n      ]\n    },\n    {\n      \"id\": \"phn_01K9R1B3D5F7H9K2M4P6R8T0W2\",\n      \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"managed\",\n      \"number\": \"+912248901234\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"state\": \"ready\",\n      \"connection_state\": \"verified\",\n      \"version\": 3,\n      \"webhook_url\": \"\",\n      \"created_at\": \"2026-10-09T06:12:44.120537Z\",\n      \"health\": {\n        \"state\": \"warming\",\n        \"resting_until\": null,\n        \"cooling_until\": null,\n        \"retired_at\": null,\n        \"warming\": {\n          \"done\": 3,\n          \"of\": 7\n        },\n        \"attempts_this_hour\": 12,\n        \"attempts_today\": 24,\n        \"answers_today\": 17,\n        \"answer_rate_7d\": 0.6955,\n        \"series_7d\": [\n          {\n            \"day\": \"2026-10-09\",\n            \"attempts\": 52,\n            \"answers\": 31\n          },\n          {\n            \"day\": \"2026-10-10\",\n            \"attempts\": 60,\n            \"answers\": 39\n          },\n          {\n            \"day\": \"2026-10-11\",\n            \"attempts\": 0,\n            \"answers\": 0\n          },\n          {\n            \"day\": \"2026-10-12\",\n            \"attempts\": 58,\n            \"answers\": 41\n          },\n          {\n            \"day\": \"2026-10-13\",\n            \"attempts\": 61,\n            \"answers\": 40\n          },\n          {\n            \"day\": \"2026-10-14\",\n            \"attempts\": 59,\n            \"answers\": 43\n          },\n          {\n            \"day\": \"2026-10-15\",\n            \"attempts\": 24,\n            \"answers\": 17\n          }\n        ],\n        \"rests_today\": 0\n      },\n      \"pools\": []\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Get phone number",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}"
              ]
            },
            "description": "One number: who answers it, whether incoming calls are on (`state`), whether its Plivo account is still connected (`connection_state`), and the `version` your next change must send."
          },
          "response": [
            {
              "name": "200 — imported, not set up yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"\",\n  \"state\": \"imported\",\n  \"connection_state\": \"verified\",\n  \"version\": 1,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\"\n}"
            },
            {
              "name": "200 — turning calls on failed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"state\": \"error\",\n  \"connection_state\": \"verified\",\n  \"version\": 3,\n  \"setup_error\": \"number already has a voice application; confirm replacing its incoming call routing\",\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\"\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Assign an agent",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": 1,\n  \"agent_id\": \"{{agent_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Chooses the agent that answers calls to this number. The agent has to be published (not a draft) and not archived. Send `\"agent_id\": \"\"` to unassign.\n\nOptional `webhook_url` (https) is where events for calls coming in on this number are sent; `\"\"` clears it.\n\n`version` is the number's current version: `1` straight after import or rental. You can change the agent while calls are on; you can't while they are being turned on."
          },
          "response": [
            {
              "name": "200 — assigned",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"agent_id\": \"{{agent_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"state\": \"imported\",\n  \"connection_state\": \"verified\",\n  \"version\": 2,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\"\n}"
            },
            {
              "name": "409 — stale version",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"agent_id\": \"{{agent_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The number/account is already connected or the configuration version changed; refresh before retrying\"\n  }\n}"
            },
            {
              "name": "409 — the agent is archived",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"agent_id\": \"{{agent_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"agent_archived\",\n    \"message\": \"restore the agent before assigning a number\"\n  }\n}"
            },
            {
              "name": "400 — the agent isn't published",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"agent_id\": \"{{agent_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Complete the agent configuration before assigning a number\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Turn on incoming calls",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/activate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}",
                "activate"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": 2,\n  \"replace_existing_application\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Points the number's voice routing in Plivo at Mirai, so people who call it reach the assigned agent. Assign an agent first. Takes a few seconds; the answer is the number with `state: ready`.\n\nIf the number already has voice routing in Plivo (another application), this stops rather than overwrite it: the number goes to `state: error` and `setup_error` says so. Send `replace_existing_application: true` to replace that routing. Numbers with SMS or MMS switched on are refused; use a voice-only number.\n\nEvery attempt, failed or not, raises `version` by one, so read the number again before you retry. A rented number whose term has ended can't be turned on. A number on your own SIP trunk is already on; this answers it as it is."
          },
          "response": [
            {
              "name": "200 — calls are on",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/activate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "activate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 2,\n  \"replace_existing_application\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"state\": \"ready\",\n  \"connection_state\": \"verified\",\n  \"version\": 3,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\"\n}"
            },
            {
              "name": "503 — it already has routing in Plivo (see setup_error)",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/activate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "activate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 2,\n  \"replace_existing_application\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"telephony_unavailable\",\n    \"message\": \"The provider operation could not finish; refresh its status before retrying\"\n  }\n}"
            },
            {
              "name": "409 — SMS is on for this number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/activate",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "activate"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 2,\n  \"replace_existing_application\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"messaging_conflict\",\n    \"message\": \"this number has messaging configured; use a dedicated voice number\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Rest a number",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/rest",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}",
                "rest"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"minutes\": 60\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Stops the number ringing out for `minutes` (1 to 1440). A campaign on it waits; a pool calls from its other numbers. People can still call it.\n\nNumbers in a pool also rest on their own when their answers drop well below their pool-mates'. Resume brings one back early."
          },
          "response": [
            {
              "name": "200 — resting",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/rest",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "rest"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"minutes\": 60\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"state\": \"ready\",\n  \"connection_state\": \"verified\",\n  \"version\": 4,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n  \"health\": {\n    \"state\": \"resting\",\n    \"resting_until\": \"2026-10-15T11:30:00Z\",\n    \"cooling_until\": null,\n    \"retired_at\": null,\n    \"warming\": null,\n    \"attempts_this_hour\": 12,\n    \"attempts_today\": 24,\n    \"answers_today\": 17,\n    \"answer_rate_7d\": 0.6955,\n    \"series_7d\": [\n      {\n        \"day\": \"2026-10-09\",\n        \"attempts\": 52,\n        \"answers\": 31\n      },\n      {\n        \"day\": \"2026-10-10\",\n        \"attempts\": 60,\n        \"answers\": 39\n      },\n      {\n        \"day\": \"2026-10-11\",\n        \"attempts\": 0,\n        \"answers\": 0\n      },\n      {\n        \"day\": \"2026-10-12\",\n        \"attempts\": 58,\n        \"answers\": 41\n      },\n      {\n        \"day\": \"2026-10-13\",\n        \"attempts\": 61,\n        \"answers\": 40\n      },\n      {\n        \"day\": \"2026-10-14\",\n        \"attempts\": 59,\n        \"answers\": 43\n      },\n      {\n        \"day\": \"2026-10-15\",\n        \"attempts\": 24,\n        \"answers\": 17\n      }\n    ],\n    \"rests_today\": 0\n  },\n  \"pools\": [\n    {\n      \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"name\": \"Outreach\"\n    }\n  ]\n}"
            },
            {
              "name": "409 — it's retired",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/rest",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "rest"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"minutes\": 60\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"number_retired\",\n    \"message\": \"This number is retired. Resume it before resting it.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Resume a number",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/resume",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}",
                "resume"
              ]
            },
            "description": "Brings a resting, cooling or retired number back now. Its answer rate starts afresh for the rest-before-it-burns check."
          },
          "response": [
            {
              "name": "200 — back in use",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/resume",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "resume"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"state\": \"ready\",\n  \"connection_state\": \"verified\",\n  \"version\": 5,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n  \"health\": {\n    \"state\": \"active\",\n    \"resting_until\": null,\n    \"cooling_until\": null,\n    \"retired_at\": null,\n    \"warming\": null,\n    \"attempts_this_hour\": 12,\n    \"attempts_today\": 24,\n    \"answers_today\": 17,\n    \"answer_rate_7d\": 0.6955,\n    \"series_7d\": [\n      {\n        \"day\": \"2026-10-09\",\n        \"attempts\": 52,\n        \"answers\": 31\n      },\n      {\n        \"day\": \"2026-10-10\",\n        \"attempts\": 60,\n        \"answers\": 39\n      },\n      {\n        \"day\": \"2026-10-11\",\n        \"attempts\": 0,\n        \"answers\": 0\n      },\n      {\n        \"day\": \"2026-10-12\",\n        \"attempts\": 58,\n        \"answers\": 41\n      },\n      {\n        \"day\": \"2026-10-13\",\n        \"attempts\": 61,\n        \"answers\": 40\n      },\n      {\n        \"day\": \"2026-10-14\",\n        \"attempts\": 59,\n        \"answers\": 43\n      },\n      {\n        \"day\": \"2026-10-15\",\n        \"attempts\": 24,\n        \"answers\": 17\n      }\n    ],\n    \"rests_today\": 0\n  },\n  \"pools\": [\n    {\n      \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"name\": \"Outreach\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Retire a number",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/retire",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}",
                "retire"
              ]
            },
            "description": "Stops the number calling out until you resume it, and takes it out of every pool's dialling. It keeps answering calls to it, so its agent is still reachable."
          },
          "response": [
            {
              "name": "200 — retired",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/retire",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "retire"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"number\": \"+918048123456\",\n  \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n  \"state\": \"ready\",\n  \"connection_state\": \"verified\",\n  \"version\": 4,\n  \"webhook_url\": \"\",\n  \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n  \"health\": {\n    \"state\": \"retired\",\n    \"resting_until\": null,\n    \"cooling_until\": null,\n    \"retired_at\": \"2026-10-15T10:30:00Z\",\n    \"warming\": null,\n    \"attempts_this_hour\": 12,\n    \"attempts_today\": 24,\n    \"answers_today\": 17,\n    \"answer_rate_7d\": 0.6955,\n    \"series_7d\": [\n      {\n        \"day\": \"2026-10-09\",\n        \"attempts\": 52,\n        \"answers\": 31\n      },\n      {\n        \"day\": \"2026-10-10\",\n        \"attempts\": 60,\n        \"answers\": 39\n      },\n      {\n        \"day\": \"2026-10-11\",\n        \"attempts\": 0,\n        \"answers\": 0\n      },\n      {\n        \"day\": \"2026-10-12\",\n        \"attempts\": 58,\n        \"answers\": 41\n      },\n      {\n        \"day\": \"2026-10-13\",\n        \"attempts\": 61,\n        \"answers\": 40\n      },\n      {\n        \"day\": \"2026-10-14\",\n        \"attempts\": 59,\n        \"answers\": 43\n      },\n      {\n        \"day\": \"2026-10-15\",\n        \"attempts\": 24,\n        \"answers\": 17\n      }\n    ],\n    \"rests_today\": 0\n  },\n  \"pools\": [\n    {\n      \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"name\": \"Outreach\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Number health history",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/health",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-numbers",
                "{{phone_number_id}}",
                "health"
              ]
            },
            "description": "The number's last 30 India days (oldest first, days without calls as zeros) and today's hours so far, beside its `health` now. What the console's charts draw."
          },
          "response": [
            {
              "name": "200 — 30 days",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-numbers/{{phone_number_id}}/health",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-numbers",
                    "{{phone_number_id}}",
                    "health"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"phone_number_health\",\n  \"phone_number_id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n  \"number\": \"+918048123456\",\n  \"health\": {\n    \"state\": \"active\",\n    \"resting_until\": null,\n    \"cooling_until\": null,\n    \"retired_at\": null,\n    \"warming\": null,\n    \"attempts_this_hour\": 12,\n    \"attempts_today\": 24,\n    \"answers_today\": 17,\n    \"answer_rate_7d\": 0.6955,\n    \"series_7d\": [\n      {\n        \"day\": \"2026-10-09\",\n        \"attempts\": 52,\n        \"answers\": 31\n      },\n      {\n        \"day\": \"2026-10-10\",\n        \"attempts\": 60,\n        \"answers\": 39\n      },\n      {\n        \"day\": \"2026-10-11\",\n        \"attempts\": 0,\n        \"answers\": 0\n      },\n      {\n        \"day\": \"2026-10-12\",\n        \"attempts\": 58,\n        \"answers\": 41\n      },\n      {\n        \"day\": \"2026-10-13\",\n        \"attempts\": 61,\n        \"answers\": 40\n      },\n      {\n        \"day\": \"2026-10-14\",\n        \"attempts\": 59,\n        \"answers\": 43\n      },\n      {\n        \"day\": \"2026-10-15\",\n        \"attempts\": 24,\n        \"answers\": 17\n      }\n    ],\n    \"rests_today\": 0\n  },\n  \"days\": [\n    {\n      \"day\": \"2026-10-15\",\n      \"attempts\": 24,\n      \"answers\": 17\n    }\n  ],\n  \"hours_today\": [\n    {\n      \"hour\": \"2026-10-15T10\",\n      \"attempts\": 12,\n      \"answers\": 9\n    }\n  ]\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Phone pools",
      "description": "A pool is a group of your own phone numbers that a campaign, an agent or a single call can ring from. Each call takes the number best placed for it: a number a contact has already been rung from stays theirs on a retry, numbers in the contact's own circle come first, and the pool's pace (`max_per_hour`, per number) is held across every campaign and API call at once. A number whose answers drop well below its pool-mates' rests on its own for 45 minutes.\n\nPoint a campaign at a pool with `pool_id` on *Create a campaign*, an agent with `calls_from: {\"pool_id\": …}`, or one call with `pool_id` on *Place a call*. `pool_id` and `phone_number_id` never go together. With nothing chosen, calls come from the agent's setting, then the pool marked `default_for_campaigns`, then the Mirai shared line. A call's `calls_from_source` is `pool` (with `pool_id`) when a pool picked its number.\n\nA single call on a pool whose numbers are all resting or at their pace this hour answers 409 `pool_busy` with `Retry-After`; one with no number that can call, 409 `pool_unavailable`. A campaign doesn't fail: it waits and carries on.\n\n`purpose` is what the calls are for: `outreach` (promotional), `reminders`, `support` or `other`. It sets the starting pace: 40 an hour for support, 60 otherwise. Pools are free; numbers are billed as numbers.",
      "item": [
        {
          "name": "Create a pool",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-pools",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-pools"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"number_ids\": [\n    \"{{phone_number_id}}\"\n  ],\n  \"max_per_hour\": 60\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "`number_ids` are your numbers (*List phone numbers*), at least one that can make calls; a retired number can't join. A number can be in several pools.\n\n`name` is 1 to 100 characters. `max_per_hour` (1 to 180) is each number's pace; above 60 an hour a number is more likely to be flagged as spam and answered less. `max_per_day` (1 to 10000) defaults to 400. `min_healthy` (0 to the pool's size, default 2 or the size if smaller) is when you hear about it: fewer healthy numbers than that sends `phone_pool.degraded`. The answer is the pool with `members`."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const pool_id = pick(\"id\");",
                  "  if (pool_id != null && pool_id !== '') pm.collectionVariables.set(\"pool_id\", String(pool_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — created",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"number_ids\": [\n    \"{{phone_number_id}}\"\n  ],\n  \"max_per_hour\": 60\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"max_per_hour\": 60,\n  \"max_per_day\": 400,\n  \"sticky_retries\": true,\n  \"auto_rest\": true,\n  \"min_healthy\": 1,\n  \"default_for_campaigns\": false,\n  \"version\": 1,\n  \"created_at\": \"2026-10-15T06:40:12.118204Z\",\n  \"updated_at\": \"2026-10-15T06:40:12.118204Z\",\n  \"number_ids\": [\n    \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\"\n  ],\n  \"object\": \"phone_pool\",\n  \"numbers\": 1,\n  \"healthy\": 1,\n  \"resting\": 0,\n  \"answer_rate_7d\": 0.6955,\n  \"used_by\": [],\n  \"members\": [\n    {\n      \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n      \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"customer\",\n      \"number\": \"+918048123456\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"state\": \"ready\",\n      \"connection_state\": \"verified\",\n      \"version\": 3,\n      \"webhook_url\": \"\",\n      \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n      \"health\": {\n        \"state\": \"active\",\n        \"resting_until\": null,\n        \"cooling_until\": null,\n        \"retired_at\": null,\n        \"warming\": null,\n        \"attempts_this_hour\": 12,\n        \"attempts_today\": 24,\n        \"answers_today\": 17,\n        \"answer_rate_7d\": 0.6955,\n        \"series_7d\": [\n          {\n            \"day\": \"2026-10-09\",\n            \"attempts\": 52,\n            \"answers\": 31\n          },\n          {\n            \"day\": \"2026-10-10\",\n            \"attempts\": 60,\n            \"answers\": 39\n          },\n          {\n            \"day\": \"2026-10-11\",\n            \"attempts\": 0,\n            \"answers\": 0\n          },\n          {\n            \"day\": \"2026-10-12\",\n            \"attempts\": 58,\n            \"answers\": 41\n          },\n          {\n            \"day\": \"2026-10-13\",\n            \"attempts\": 61,\n            \"answers\": 40\n          },\n          {\n            \"day\": \"2026-10-14\",\n            \"attempts\": 59,\n            \"answers\": 43\n          },\n          {\n            \"day\": \"2026-10-15\",\n            \"attempts\": 24,\n            \"answers\": 17\n          }\n        ],\n        \"rests_today\": 0\n      },\n      \"pools\": [\n        {\n          \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n          \"name\": \"Outreach\"\n        }\n      ]\n    }\n  ]\n}"
            },
            {
              "name": "400 — every number chosen is resting",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"number_ids\": [\n    \"{{phone_number_id}}\"\n  ],\n  \"max_per_hour\": 60\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"a pool needs at least one number that can call now; every number chosen is resting or cooling\"\n  }\n}"
            },
            {
              "name": "400 — a retired number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"number_ids\": [\n    \"{{phone_number_id}}\"\n  ],\n  \"max_per_hour\": 60\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"+918048123456 is retired and cannot join a pool; resume it first\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List pools",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-pools",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-pools"
              ]
            },
            "description": "Every pool with how it is doing: `numbers` (its size), `healthy` (can call now), `resting` (resting or cooling), the last seven days' `answer_rate_7d`, and `used_by`, the campaigns and agents that call from it."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n      \"name\": \"Outreach\",\n      \"purpose\": \"outreach\",\n      \"max_per_hour\": 60,\n      \"max_per_day\": 400,\n      \"sticky_retries\": true,\n      \"auto_rest\": true,\n      \"min_healthy\": 2,\n      \"default_for_campaigns\": false,\n      \"version\": 1,\n      \"created_at\": \"2026-10-15T06:40:12.118204Z\",\n      \"updated_at\": \"2026-10-15T06:40:12.118204Z\",\n      \"number_ids\": [\n        \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n        \"phn_01K9R1B3D5F7H9K2M4P6R8T0W2\"\n      ],\n      \"object\": \"phone_pool\",\n      \"numbers\": 2,\n      \"healthy\": 2,\n      \"resting\": 0,\n      \"answer_rate_7d\": 0.6412,\n      \"used_by\": [\n        {\n          \"campaign_id\": \"cmp_01K9W1A3C5E7G9J1M3P5R7T9V1\",\n          \"name\": \"Diwali order confirmation\"\n        }\n      ]\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Get a pool",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-pools",
                "{{pool_id}}"
              ]
            },
            "description": "One pool, with `members`: each of its numbers and that number's own `health`."
          },
          "response": [
            {
              "name": "200 — with its numbers",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools",
                    "{{pool_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"max_per_hour\": 60,\n  \"max_per_day\": 400,\n  \"sticky_retries\": true,\n  \"auto_rest\": true,\n  \"min_healthy\": 2,\n  \"default_for_campaigns\": false,\n  \"version\": 1,\n  \"created_at\": \"2026-10-15T06:40:12.118204Z\",\n  \"updated_at\": \"2026-10-15T06:40:12.118204Z\",\n  \"number_ids\": [\n    \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\"\n  ],\n  \"object\": \"phone_pool\",\n  \"numbers\": 1,\n  \"healthy\": 1,\n  \"resting\": 0,\n  \"answer_rate_7d\": 0.6412,\n  \"used_by\": [\n    {\n      \"campaign_id\": \"cmp_01K9W1A3C5E7G9J1M3P5R7T9V1\",\n      \"name\": \"Diwali order confirmation\"\n    }\n  ],\n  \"members\": [\n    {\n      \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n      \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"customer\",\n      \"number\": \"+918048123456\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"state\": \"ready\",\n      \"connection_state\": \"verified\",\n      \"version\": 3,\n      \"webhook_url\": \"\",\n      \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n      \"health\": {\n        \"state\": \"active\",\n        \"resting_until\": null,\n        \"cooling_until\": null,\n        \"retired_at\": null,\n        \"warming\": null,\n        \"attempts_this_hour\": 12,\n        \"attempts_today\": 24,\n        \"answers_today\": 17,\n        \"answer_rate_7d\": 0.6955,\n        \"series_7d\": [\n          {\n            \"day\": \"2026-10-09\",\n            \"attempts\": 52,\n            \"answers\": 31\n          },\n          {\n            \"day\": \"2026-10-10\",\n            \"attempts\": 60,\n            \"answers\": 39\n          },\n          {\n            \"day\": \"2026-10-11\",\n            \"attempts\": 0,\n            \"answers\": 0\n          },\n          {\n            \"day\": \"2026-10-12\",\n            \"attempts\": 58,\n            \"answers\": 41\n          },\n          {\n            \"day\": \"2026-10-13\",\n            \"attempts\": 61,\n            \"answers\": 40\n          },\n          {\n            \"day\": \"2026-10-14\",\n            \"attempts\": 59,\n            \"answers\": 43\n          },\n          {\n            \"day\": \"2026-10-15\",\n            \"attempts\": 24,\n            \"answers\": 17\n          }\n        ],\n        \"rests_today\": 0\n      },\n      \"pools\": [\n        {\n          \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n          \"name\": \"Outreach\"\n        }\n      ]\n    }\n  ]\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools",
                    "{{pool_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Pool not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Change a pool",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-pools",
                "{{pool_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": 1,\n  \"max_per_hour\": 50\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Send the pool's current `version` and the fields to change; `number_ids` replaces the whole list. A change applies from the next call; a contact keeps its number while that number stays in the pool. A stale version is a 409 and changes nothing."
          },
          "response": [
            {
              "name": "200 — changed",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools",
                    "{{pool_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"max_per_hour\": 50\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"name\": \"Outreach\",\n  \"purpose\": \"outreach\",\n  \"max_per_hour\": 50,\n  \"max_per_day\": 400,\n  \"sticky_retries\": true,\n  \"auto_rest\": true,\n  \"min_healthy\": 2,\n  \"default_for_campaigns\": false,\n  \"version\": 2,\n  \"created_at\": \"2026-10-15T06:40:12.118204Z\",\n  \"updated_at\": \"2026-10-15T06:40:12.118204Z\",\n  \"number_ids\": [\n    \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\"\n  ],\n  \"object\": \"phone_pool\",\n  \"numbers\": 1,\n  \"healthy\": 1,\n  \"resting\": 0,\n  \"answer_rate_7d\": 0.6412,\n  \"used_by\": [\n    {\n      \"campaign_id\": \"cmp_01K9W1A3C5E7G9J1M3P5R7T9V1\",\n      \"name\": \"Diwali order confirmation\"\n    }\n  ],\n  \"members\": [\n    {\n      \"id\": \"phn_01K9Q3A7C2E4G6J8M0P2R4T6V8\",\n      \"connection_id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"customer\",\n      \"number\": \"+918048123456\",\n      \"agent_id\": \"agt_01K2M4P7QRSTVWXYZ0A1B2C3\",\n      \"state\": \"ready\",\n      \"connection_state\": \"verified\",\n      \"version\": 3,\n      \"webhook_url\": \"\",\n      \"created_at\": \"2026-10-09T07:02:11.903215Z\",\n      \"health\": {\n        \"state\": \"active\",\n        \"resting_until\": null,\n        \"cooling_until\": null,\n        \"retired_at\": null,\n        \"warming\": null,\n        \"attempts_this_hour\": 12,\n        \"attempts_today\": 24,\n        \"answers_today\": 17,\n        \"answer_rate_7d\": 0.6955,\n        \"series_7d\": [\n          {\n            \"day\": \"2026-10-09\",\n            \"attempts\": 52,\n            \"answers\": 31\n          },\n          {\n            \"day\": \"2026-10-10\",\n            \"attempts\": 60,\n            \"answers\": 39\n          },\n          {\n            \"day\": \"2026-10-11\",\n            \"attempts\": 0,\n            \"answers\": 0\n          },\n          {\n            \"day\": \"2026-10-12\",\n            \"attempts\": 58,\n            \"answers\": 41\n          },\n          {\n            \"day\": \"2026-10-13\",\n            \"attempts\": 61,\n            \"answers\": 40\n          },\n          {\n            \"day\": \"2026-10-14\",\n            \"attempts\": 59,\n            \"answers\": 43\n          },\n          {\n            \"day\": \"2026-10-15\",\n            \"attempts\": 24,\n            \"answers\": 17\n          }\n        ],\n        \"rests_today\": 0\n      },\n      \"pools\": [\n        {\n          \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n          \"name\": \"Outreach\"\n        }\n      ]\n    }\n  ]\n}"
            },
            {
              "name": "409 — stale version",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools",
                    "{{pool_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"max_per_hour\": 50\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The pool changed since you read it; refresh before retrying\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Delete a pool",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "phone-pools",
                "{{pool_id}}"
              ]
            },
            "description": "Its numbers stay yours and keep answering. A pool a campaign or an agent still calls from can't be deleted: 409 `pool_in_use` names them."
          },
          "response": [
            {
              "name": "200 — deleted",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools",
                    "{{pool_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2\",\n  \"object\": \"phone_pool\",\n  \"deleted\": true\n}"
            },
            {
              "name": "409 — a campaign or an agent uses it",
              "originalRequest": {
                "method": "DELETE",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/phone-pools/{{pool_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "phone-pools",
                    "{{pool_id}}"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"pool_in_use\",\n    \"message\": \"Outreach is used by campaigns Diwali order confirmation and agents COD confirm; move them to another pool or number first\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Telephony",
      "description": "Getting a phone number for your agent. There are two ways, and a workspace can use both.\n\n**1. Rent a number from Mirai.** ₹500 a month, paid as ₹1,500 from your wallet every three months, renewing until you turn it off. Indian numbers need a business verification that Plivo approves once: read the requirements, submit your details and documents, then refresh until it's `accepted`. After that: search, quote, rent. The rented number appears in **Phone numbers** by itself.\n\n**2. Connect your own Plivo account.** Plivo keeps billing you directly. Connect it with your Auth ID and Auth Token, list the numbers it owns, and bring one over with *Phone numbers → Import a Plivo number*. A Plivo main account can also rent new numbers through the same search → quote → rent requests, with its connection id as `account`.\n\n**3. Connect your own SIP trunk**, where *Get number options* lists `sip` for your workspace. Your carrier keeps billing you for the trunk. Tell us the carrier's address and the IP addresses it calls from, give your carrier the details in `sip` from *Get number options*, then add the trunk's numbers by number with *Phone numbers → Add a number on your SIP trunk*.\n\nEither way you finish in **Phone numbers**: assign the agent that answers, then turn on incoming calls.\n\nThe last two requests verify your own phone, so the workspace can ring it from Mirai's shared test number (test calls are placed from the Numbers page in the console).\n\nIndian (+91) numbers only for now. If phone numbers aren't available on the host you're calling, every request here answers 503 `telephony_unavailable`.",
      "item": [
        {
          "name": "Get number options",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/options",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "options"
              ]
            },
            "description": "What this workspace can do right now. `rentals_enabled` says whether you can rent; `managed_ready` turns true once your business verification is approved and your Mirai number account is set up. `mirai_terms` are the rental terms in paise: `amount_paise: 150000` is ₹1,500 every `term_months: 3`, with no setup fee and call minutes billed separately. `shared_test` is Mirai's shared test number.\n\n`sip` is there only when your workspace can connect its own SIP trunk. It is what to give your carrier: our SIP `address` and `port` and the `transports` we take, the `signalling_ips` and `media_ips` to allow, the `media_ports` range (UDP) and the `codecs` we speak, plus the `number_formats` a trunk may use."
          },
          "response": [
            {
              "name": "200 — rentals on, verification not done yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/options",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "options"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"countries\": [\n    \"IN\"\n  ],\n  \"inventory_enabled\": true,\n  \"managed_ready\": false,\n  \"mirai_terms\": {\n    \"amount_paise\": 150000,\n    \"auto_renew\": true,\n    \"currency\": \"INR\",\n    \"insufficient_balance\": \"notify_and_release\",\n    \"monthly_amount_paise\": 50000,\n    \"setup_amount_paise\": 0,\n    \"term_months\": 3,\n    \"usage_billed_separately\": true\n  },\n  \"onboarding_enabled\": true,\n  \"provider\": \"plivo\",\n  \"rentals_enabled\": true,\n  \"shared_test\": {\n    \"daily_limit\": 3,\n    \"enabled\": true,\n    \"max_duration_secs\": 60,\n    \"number\": \"+918035739450\",\n    \"verified_phone_required\": true\n  }\n}"
            },
            {
              "name": "200 — SIP trunks on for this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/options",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "options"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"countries\": [\n    \"IN\"\n  ],\n  \"inventory_enabled\": true,\n  \"managed_ready\": true,\n  \"onboarding_enabled\": true,\n  \"provider\": \"plivo\",\n  \"rentals_enabled\": true,\n  \"sip\": {\n    \"address\": \"sip.miraiminds.co\",\n    \"port\": 5060,\n    \"transports\": [\n      \"udp\",\n      \"tcp\"\n    ],\n    \"signalling_ips\": [\n      \"168.220.248.249\"\n    ],\n    \"media_ips\": [\n      \"168.220.248.249\"\n    ],\n    \"media_ports\": \"20000-29999\",\n    \"codecs\": [\n      \"PCMU\",\n      \"PCMA\"\n    ],\n    \"number_formats\": [\n      \"e164\",\n      \"e164_digits\",\n      \"national\",\n      \"local\"\n    ]\n  }\n}"
            },
            {
              "name": "503 — phone numbers aren't switched on here",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/options",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "options"
                  ]
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"telephony_unavailable\",\n    \"message\": \"Customer phone numbers are not configured on this deployment\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get verification requirements",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/requirements?account=mirai&number_type=local",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "requirements"
              ],
              "query": [
                {
                  "key": "account",
                  "value": "mirai",
                  "description": "mirai, or your connection id"
                },
                {
                  "key": "number_type",
                  "value": "local",
                  "description": "local | mobile | tollfree"
                }
              ]
            },
            "description": "The documents and fields Plivo currently asks for to verify an Indian business, for one `number_type` (`local`, `mobile` or `tollfree`). It comes straight from Plivo and can change, so read it right before you submit. Your submission must carry this `requirement_id` and one entry for every item in `document_types`.\n\n`account` is `mirai` to rent from Mirai, or a connection id to verify your own Plivo main account."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const requirement_id = pick(\"requirement_id\");",
                  "  if (requirement_id != null && requirement_id !== '') pm.collectionVariables.set(\"requirement_id\", String(requirement_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — what Plivo asks for",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/requirements?account=mirai&number_type=local",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "requirements"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "number_type",
                      "value": "local",
                      "description": "local | mobile | tollfree"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"requirement_id\": \"9a3c5e71-2b4d-4f86-a1c9-7e0d2f4b6a83\",\n  \"country_iso\": \"IN\",\n  \"number_type\": \"local\",\n  \"user_type\": \"business\",\n  \"document_types\": [\n    {\n      \"document_type_id\": \"3b6f0d2a-8c41-4e7b-a5d9-1f2e3c4b5a60\",\n      \"name\": \"Certificate of Incorporation\",\n      \"description\": \"Issued by the Registrar of Companies.\",\n      \"proof_required\": true,\n      \"required_fields\": [\n        {\n          \"field_name\": \"business_name\",\n          \"friendly_name\": \"Business name\",\n          \"field_type\": \"string\",\n          \"required\": true,\n          \"min_length\": 1,\n          \"max_length\": 255,\n          \"help_text\": \"As printed on the certificate.\"\n        },\n        {\n          \"field_name\": \"date_of_incorporation\",\n          \"friendly_name\": \"Date of incorporation\",\n          \"field_type\": \"date\",\n          \"required\": true,\n          \"help_text\": \"YYYY-MM-DD\"\n        }\n      ]\n    },\n    {\n      \"document_type_id\": \"7d2e9b14-5a63-4c08-b1f7-6e3a0c9d2b85\",\n      \"name\": \"Letter of Authorisation\",\n      \"description\": \"On company letterhead, signed and stamped with the company seal.\",\n      \"proof_required\": true,\n      \"required_fields\": []\n    }\n  ]\n}"
            },
            {
              "name": "404 — unknown connection id",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/requirements?account=mirai&number_type=local",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "requirements"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "number_type",
                      "value": "local",
                      "description": "local | mobile | tollfree"
                    }
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get business verification",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/onboarding?account=mirai&number_type=local",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "onboarding"
              ],
              "query": [
                {
                  "key": "account",
                  "value": "mirai",
                  "description": "mirai, or your connection id"
                },
                {
                  "key": "number_type",
                  "value": "local",
                  "description": "local | mobile | tollfree"
                }
              ]
            },
            "description": "Where your business verification stands for one `account` and `number_type`. Read-only.\n\n`state` is `not_started` until you submit, `submitted` while Plivo reviews it, then `accepted` or `rejected` (also possible: `submission_failed`, `suspended`, `expired`). `setup_state` turns `ready` when you can rent.\n\n`business_defaults` are the company details you saved when going live, ready to reuse in the application; editing them in the application doesn't change your billing details. Send this `version` when you submit (`0` the first time)."
          },
          "response": [
            {
              "name": "200 — not started",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding?account=mirai&number_type=local",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "number_type",
                      "value": "local",
                      "description": "local | mobile | tollfree"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"\",\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"state\": \"not_started\",\n  \"compliance_id\": \"\",\n  \"request_id\": \"\",\n  \"version\": 0,\n  \"setup_state\": \"not_started\",\n  \"business_defaults\": {\n    \"name\": \"Mirai Motors Private Limited\",\n    \"email\": \"accounts@example.com\",\n    \"address_line1\": \"4th Floor, Example House, 12 MG Road\",\n    \"address_line2\": \"Camp\",\n    \"city\": \"Pune\",\n    \"state\": \"Maharashtra\",\n    \"postal_code\": \"411001\",\n    \"registration_number\": \"27AAACM1234A1Z5\"\n  },\n  \"business_source\": \"company_profile\"\n}"
            },
            {
              "name": "200 — under review",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding?account=mirai&number_type=local",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "number_type",
                      "value": "local",
                      "description": "local | mobile | tollfree"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tbo_01K9N4R7T0W3Y6B9D2G5J8M1P4\",\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"state\": \"submitted\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"version\": 3,\n  \"setup_state\": \"not_started\",\n  \"business_defaults\": {\n    \"name\": \"Mirai Motors Private Limited\",\n    \"email\": \"accounts@example.com\",\n    \"address_line1\": \"4th Floor, Example House, 12 MG Road\",\n    \"address_line2\": \"Camp\",\n    \"city\": \"Pune\",\n    \"state\": \"Maharashtra\",\n    \"postal_code\": \"411001\",\n    \"registration_number\": \"27AAACM1234A1Z5\"\n  },\n  \"business_source\": \"company_profile\"\n}"
            },
            {
              "name": "400 — unknown number type",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding?account=mirai&number_type=local",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "number_type",
                      "value": "local",
                      "description": "local | mobile | tollfree"
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Choose a supported India number type\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Submit business verification",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/onboarding",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "onboarding"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"version\": 0,\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"consent\": true,\n  \"application\": {\n    \"requirement_id\": \"{{requirement_id}}\",\n    \"business\": {\n      \"name\": \"Mirai Motors Private Limited\",\n      \"email\": \"accounts@example.com\",\n      \"address_line1\": \"4th Floor, Example House, 12 MG Road\",\n      \"address_line2\": \"Camp\",\n      \"city\": \"Pune\",\n      \"state\": \"Maharashtra\",\n      \"postal_code\": \"411001\",\n      \"registration_number\": \"27AAACM1234A1Z5\"\n    },\n    \"documents\": [\n      {\n        \"document_type_id\": \"3b6f0d2a-8c41-4e7b-a5d9-1f2e3c4b5a60\",\n        \"data_fields\": {\n          \"business_name\": \"Mirai Motors Private Limited\",\n          \"date_of_incorporation\": \"2019-04-01\"\n        },\n        \"file_name\": \"certificate-of-incorporation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      },\n      {\n        \"document_type_id\": \"7d2e9b14-5a63-4c08-b1f7-6e3a0c9d2b85\",\n        \"data_fields\": {},\n        \"file_name\": \"letter-of-authorisation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      }\n    ]\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sends your business details and documents to Plivo for review. It doesn't buy a number or charge your wallet. The documents go to Plivo; Mirai doesn't keep a copy.\n\n**Replace every value below with your own.** The example document is a placeholder. Give one `documents` entry per item in *Get verification requirements* (at most four), with that item's `document_type_id` and its `required_fields` in `data_fields`. Where `proof_required` is true, attach the file as `content_base64` (PDF, JPEG or PNG, 5 MB each) with a `file_name` whose extension matches.\n\n`consent: true` confirms you're authorised to submit these for your business. `version` is `0` for a first application, otherwise the current one from *Get business verification*.\n\n`request_id` is a unique id you choose. If the request is cut off, send exactly the same body again with the same `request_id`: it returns the application without uploading twice. Only a `submission_failed` or `rejected` application can be corrected, with a new `request_id` and all documents again.\n\nAnswers 202 with the application. Plivo's review takes time; check on it with *Refresh business verification*."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const onboarding_id = pick(\"id\");",
                  "  if (onboarding_id != null && onboarding_id !== '') pm.collectionVariables.set(\"onboarding_id\", String(onboarding_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "202 — sent to Plivo for review",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"version\": 0,\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"consent\": true,\n  \"application\": {\n    \"requirement_id\": \"{{requirement_id}}\",\n    \"business\": {\n      \"name\": \"Mirai Motors Private Limited\",\n      \"email\": \"accounts@example.com\",\n      \"address_line1\": \"4th Floor, Example House, 12 MG Road\",\n      \"address_line2\": \"Camp\",\n      \"city\": \"Pune\",\n      \"state\": \"Maharashtra\",\n      \"postal_code\": \"411001\",\n      \"registration_number\": \"27AAACM1234A1Z5\"\n    },\n    \"documents\": [\n      {\n        \"document_type_id\": \"3b6f0d2a-8c41-4e7b-a5d9-1f2e3c4b5a60\",\n        \"data_fields\": {\n          \"business_name\": \"Mirai Motors Private Limited\",\n          \"date_of_incorporation\": \"2019-04-01\"\n        },\n        \"file_name\": \"certificate-of-incorporation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      },\n      {\n        \"document_type_id\": \"7d2e9b14-5a63-4c08-b1f7-6e3a0c9d2b85\",\n        \"data_fields\": {},\n        \"file_name\": \"letter-of-authorisation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      }\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tbo_01K9N4R7T0W3Y6B9D2G5J8M1P4\",\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"state\": \"submitted\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"version\": 3,\n  \"setup_state\": \"not_started\"\n}"
            },
            {
              "name": "400 — requirements changed since you read them",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"version\": 0,\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"consent\": true,\n  \"application\": {\n    \"requirement_id\": \"{{requirement_id}}\",\n    \"business\": {\n      \"name\": \"Mirai Motors Private Limited\",\n      \"email\": \"accounts@example.com\",\n      \"address_line1\": \"4th Floor, Example House, 12 MG Road\",\n      \"address_line2\": \"Camp\",\n      \"city\": \"Pune\",\n      \"state\": \"Maharashtra\",\n      \"postal_code\": \"411001\",\n      \"registration_number\": \"27AAACM1234A1Z5\"\n    },\n    \"documents\": [\n      {\n        \"document_type_id\": \"3b6f0d2a-8c41-4e7b-a5d9-1f2e3c4b5a60\",\n        \"data_fields\": {\n          \"business_name\": \"Mirai Motors Private Limited\",\n          \"date_of_incorporation\": \"2019-04-01\"\n        },\n        \"file_name\": \"certificate-of-incorporation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      },\n      {\n        \"document_type_id\": \"7d2e9b14-5a63-4c08-b1f7-6e3a0c9d2b85\",\n        \"data_fields\": {},\n        \"file_name\": \"letter-of-authorisation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      }\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_application\",\n    \"message\": \"Verification requirements changed. Reload the form before submitting.\"\n  }\n}"
            },
            {
              "name": "409 — an application is already under review",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"version\": 0,\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"consent\": true,\n  \"application\": {\n    \"requirement_id\": \"{{requirement_id}}\",\n    \"business\": {\n      \"name\": \"Mirai Motors Private Limited\",\n      \"email\": \"accounts@example.com\",\n      \"address_line1\": \"4th Floor, Example House, 12 MG Road\",\n      \"address_line2\": \"Camp\",\n      \"city\": \"Pune\",\n      \"state\": \"Maharashtra\",\n      \"postal_code\": \"411001\",\n      \"registration_number\": \"27AAACM1234A1Z5\"\n    },\n    \"documents\": [\n      {\n        \"document_type_id\": \"3b6f0d2a-8c41-4e7b-a5d9-1f2e3c4b5a60\",\n        \"data_fields\": {\n          \"business_name\": \"Mirai Motors Private Limited\",\n          \"date_of_incorporation\": \"2019-04-01\"\n        },\n        \"file_name\": \"certificate-of-incorporation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      },\n      {\n        \"document_type_id\": \"7d2e9b14-5a63-4c08-b1f7-6e3a0c9d2b85\",\n        \"data_fields\": {},\n        \"file_name\": \"letter-of-authorisation.pdf\",\n        \"content_base64\": \"JVBERi0xLjQKJSBQbGFjZWhvbGRlcjogcmVwbGFjZSBjb250ZW50X2Jhc2U2NCB3aXRoIHlvdXIgcmVhbCBkb2N1bWVudCwgYmFzZTY0LWVuY29kZWQuCg==\"\n      }\n    ]\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"verification_in_progress\",\n    \"message\": \"Refresh verification before submitting. An existing application may still be under review.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Refresh business verification",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/onboarding/{{onboarding_id}}/refresh",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "onboarding",
                "{{onboarding_id}}",
                "refresh"
              ]
            },
            "description": "Asks Plivo for the latest on your application. There's no webhook for this, so call it to check. For a Mirai rental, the refresh that finds it `accepted` also finishes setting up your Mirai number account; `setup_state: ready` means you can rent. A rejection comes back with `rejection_reason`.\n\nDoesn't rent a number or charge anything. Safe to repeat."
          },
          "response": [
            {
              "name": "200 — approved, ready to rent",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding/{{onboarding_id}}/refresh",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding",
                    "{{onboarding_id}}",
                    "refresh"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tbo_01K9N4R7T0W3Y6B9D2G5J8M1P4\",\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"state\": \"accepted\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"version\": 4,\n  \"setup_state\": \"ready\"\n}"
            },
            {
              "name": "200 — rejected",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding/{{onboarding_id}}/refresh",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding",
                    "{{onboarding_id}}",
                    "refresh"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tbo_01K9N4R7T0W3Y6B9D2G5J8M1P4\",\n  \"account\": \"mirai\",\n  \"number_type\": \"local\",\n  \"state\": \"rejected\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"request_id\": \"business-verification-local-2026-10-02\",\n  \"version\": 4,\n  \"setup_state\": \"not_started\",\n  \"rejection_reason\": \"The Letter of Authorisation is not stamped with the company seal.\"\n}"
            },
            {
              "name": "404 — unknown application",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/onboarding/{{onboarding_id}}/refresh",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "onboarding",
                    "{{onboarding_id}}",
                    "refresh"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List business verifications",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/compliances?account=mirai",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "compliances"
              ],
              "query": [
                {
                  "key": "account",
                  "value": "mirai",
                  "description": "mirai, or your connection id"
                }
              ]
            },
            "description": "Your business verifications for an account. To quote a number you need one with `status: accepted` whose `number_type` matches the number. With `account=mirai` and nothing on file yet, `data` is empty and `status` is `verification_required`.\n\nFor your own Plivo account this lists the approved applications in Plivo. A subaccount can't rent new numbers; connect the main account for that."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const compliance_id = pick(\"data.0.compliance_id\");",
                  "  if (compliance_id != null && compliance_id !== '') pm.collectionVariables.set(\"compliance_id\", String(compliance_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — approved",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/compliances?account=mirai",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "compliances"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n      \"alias\": \"mirai-tbo_01K9N4R7T0W3Y6B9D2G5J8M1P4\",\n      \"status\": \"accepted\",\n      \"country_iso\": \"IN\",\n      \"number_type\": \"local\",\n      \"user_type\": \"business\",\n      \"updated_at\": \"2026-10-05T09:41:22.513942Z\"\n    }\n  ],\n  \"status\": \"select_approved_application\"\n}"
            },
            {
              "name": "200 — nothing verified yet",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/compliances?account=mirai",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "compliances"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [],\n  \"message\": \"Complete business verification with Mirai before renting an Indian number.\",\n  \"status\": \"verification_required\"\n}"
            },
            {
              "name": "409 — a Plivo subaccount",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/compliances?account=mirai",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "compliances"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    }
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"parent_account_required\",\n    \"message\": \"Connect your main Plivo account to rent numbers. Subaccounts can import numbers they already own.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List cities with numbers",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/available-cities?account=mirai&country=IN",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "available-cities"
              ],
              "query": [
                {
                  "key": "account",
                  "value": "mirai",
                  "description": "mirai, or your connection id"
                },
                {
                  "key": "country",
                  "value": "IN"
                }
              ]
            },
            "description": "The Indian cities that have a landline free to rent right now (`country=IN` is required). Pass a city's `id` as `city` when you search numbers. `std_code` is the city's dialling code: every landline there starts with it. The list is checked at most every ten minutes."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const city = pick(\"data.0.id\");",
                  "  if (city != null && city !== '') pm.collectionVariables.set(\"city\", String(city));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — cities in stock",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/available-cities?account=mirai&country=IN",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "available-cities"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "country",
                      "value": "IN"
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"mumbai\",\n      \"name\": \"Mumbai\",\n      \"state\": \"Maharashtra\",\n      \"std_code\": \"22\"\n    },\n    {\n      \"id\": \"bengaluru\",\n      \"name\": \"Bengaluru\",\n      \"state\": \"Karnataka\",\n      \"std_code\": \"80\"\n    }\n  ],\n  \"has_more\": false\n}"
            },
            {
              "name": "400 — not India",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/available-cities?account=mirai&country=IN",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "available-cities"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "country",
                      "value": "IN"
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Choose India (IN)\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Search available numbers",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/available-numbers?account=mirai&country=IN",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "available-numbers"
              ],
              "query": [
                {
                  "key": "account",
                  "value": "mirai",
                  "description": "mirai, or your connection id"
                },
                {
                  "key": "country",
                  "value": "IN"
                },
                {
                  "key": "city",
                  "value": "{{city}}",
                  "description": "a city id from List cities with numbers",
                  "disabled": true
                },
                {
                  "key": "location",
                  "value": "Maharashtra",
                  "description": "a region, up to 100 characters",
                  "disabled": true
                },
                {
                  "key": "pattern",
                  "value": "22",
                  "description": "digits the number should contain",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "20",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Numbers Plivo has free to rent in India right now (`country=IN` is required). `city` (an `id` from List cities with numbers) returns that city's landlines. Without it you can narrow by Plivo's `location` region, or by `pattern`, the digits the number starts with. Nothing is held for you: availability is checked again when you quote and when you buy. 20 per page; pass `next_cursor` back as `cursor`.\n\nThe rates are Plivo's, in USD. That's what Plivo bills when you rent through your own account. A Mirai rental is ₹500 a month whatever the number. `compliance_type` is the verification type the number needs."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const available_number = pick(\"data.0.number\");",
                  "  if (available_number != null && available_number !== '') pm.collectionVariables.set(\"available_number\", String(available_number));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/available-numbers?account=mirai&country=IN",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "available-numbers"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "country",
                      "value": "IN"
                    },
                    {
                      "key": "city",
                      "value": "{{city}}",
                      "description": "a city id from List cities with numbers",
                      "disabled": true
                    },
                    {
                      "key": "location",
                      "value": "Maharashtra",
                      "description": "a region, up to 100 characters",
                      "disabled": true
                    },
                    {
                      "key": "pattern",
                      "value": "22",
                      "description": "digits the number should contain",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "20",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"number\": \"+912248901234\",\n      \"country\": \"IN\",\n      \"region\": \"Maharashtra\",\n      \"city\": \"Mumbai\",\n      \"type\": \"fixed\",\n      \"sub_type\": \"local\",\n      \"compliance_type\": \"local\",\n      \"voice_enabled\": true,\n      \"monthly_rental_rate\": \"2.50000\",\n      \"setup_rate\": \"0.00000\",\n      \"currency\": \"USD\",\n      \"restriction\": \"\"\n    }\n  ],\n  \"has_more\": true,\n  \"next_cursor\": \"20\"\n}"
            },
            {
              "name": "400 — not India",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/available-numbers?account=mirai&country=IN",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "available-numbers"
                  ],
                  "query": [
                    {
                      "key": "account",
                      "value": "mirai",
                      "description": "mirai, or your connection id"
                    },
                    {
                      "key": "country",
                      "value": "IN"
                    },
                    {
                      "key": "city",
                      "value": "{{city}}",
                      "description": "a city id from List cities with numbers",
                      "disabled": true
                    },
                    {
                      "key": "location",
                      "value": "Maharashtra",
                      "description": "a region, up to 100 characters",
                      "disabled": true
                    },
                    {
                      "key": "pattern",
                      "value": "22",
                      "description": "digits the number should contain",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "20",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Choose India (IN), a valid location and cursor\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Quote a number",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/quotes",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "quotes"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"account\": \"mirai\",\n  \"number\": \"{{available_number}}\",\n  \"compliance_id\": \"{{compliance_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Fixes the price for ten minutes (`expires_at`) after checking the number is still free and your business verification covers it. Nothing is bought or charged yet.\n\n`account` and `number` are required. `compliance_id` is the approved verification to use: optional for a Mirai rental (the approved one on file is used), required when you rent through your own Plivo account.\n\n`amount_paise` is what a Mirai rental charges per term (`150000` = ₹1,500 for 3 months); it's `0` through your own Plivo account, where Plivo bills the `provider_*` rates in USD."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const rental_id = pick(\"id\");",
                  "  if (rental_id != null && rental_id !== '') pm.collectionVariables.set(\"rental_id\", String(rental_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — quoted for ten minutes",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/quotes",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "quotes"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"account\": \"mirai\",\n  \"number\": \"{{available_number}}\",\n  \"compliance_id\": \"{{compliance_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9\",\n  \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n  \"number\": \"+912248901234\",\n  \"ownership\": \"managed\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"number_type\": \"local\",\n  \"provider_monthly_rate\": \"2.50000\",\n  \"provider_setup_rate\": \"0.00000\",\n  \"state\": \"quoted\",\n  \"phone_number_id\": \"\",\n  \"amount_paise\": 150000,\n  \"term_months\": 3,\n  \"expires_at\": \"2026-10-09T06:20:02.418356Z\",\n  \"purchased_at\": null,\n  \"renews_at\": null,\n  \"cancel_at_period_end\": false,\n  \"release_reason\": \"\",\n  \"created_at\": \"2026-10-09T06:10:02.418356Z\"\n}"
            },
            {
              "name": "409 — someone else took it",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/quotes",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "quotes"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"account\": \"mirai\",\n  \"number\": \"{{available_number}}\",\n  \"compliance_id\": \"{{compliance_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"number_unavailable\",\n    \"message\": \"This number is no longer available; search again\"\n  }\n}"
            },
            {
              "name": "409 — no approved verification for this number type",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/quotes",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "quotes"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"account\": \"mirai\",\n  \"number\": \"{{available_number}}\",\n  \"compliance_id\": \"{{compliance_id}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"verification_required\",\n    \"message\": \"Select an approved business verification for this number type\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Rent the quoted number",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}/purchase",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "rentals",
                "{{rental_id}}",
                "purchase"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"accept_terms\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "**This rents a real number.** A Mirai rental debits ₹1,500 from your wallet now and again every three months until you turn auto-renewal off. If the wallet can't cover a renewal, we email you and release the number, with no grace period. Renting through your own Plivo account, Plivo bills you its rates and Mirai charges nothing for the number. A Mirai rental needs a live (production) workspace.\n\n`accept_terms: true` is required. The answer is the rental with `state: active` and `phone_number_id`: the number is now in **Phone numbers**, ready for an agent.\n\nIf this times out or answers 503, send it again with the same rental id. It carries on from where it stopped and never buys twice. Don't make a new quote for a purchase you're unsure about."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const phone_number_id = pick(\"phone_number_id\");",
                  "  if (phone_number_id != null && phone_number_id !== '') pm.collectionVariables.set(\"phone_number_id\", String(phone_number_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — rented",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}/purchase",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}",
                    "purchase"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"accept_terms\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9\",\n  \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n  \"number\": \"+912248901234\",\n  \"ownership\": \"managed\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"number_type\": \"local\",\n  \"provider_monthly_rate\": \"2.50000\",\n  \"provider_setup_rate\": \"0.00000\",\n  \"state\": \"active\",\n  \"phone_number_id\": \"phn_01K9R1B3D5F7H9K2M4P6R8T0W2\",\n  \"amount_paise\": 150000,\n  \"term_months\": 3,\n  \"expires_at\": \"2026-10-09T06:20:02.418356Z\",\n  \"purchased_at\": \"2026-10-09T06:12:44.120537Z\",\n  \"renews_at\": \"2027-01-09T06:12:44.120537Z\",\n  \"cancel_at_period_end\": false,\n  \"release_reason\": \"\",\n  \"created_at\": \"2026-10-09T06:10:02.418356Z\"\n}"
            },
            {
              "name": "402 — wallet can't cover ₹1,500",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}/purchase",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}",
                    "purchase"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"accept_terms\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"Add ₹1,500 of available credit to your wallet before renting this number\"\n  }\n}"
            },
            {
              "name": "503 — not finished yet: send it again",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}/purchase",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}",
                    "purchase"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"accept_terms\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"telephony_unavailable\",\n    \"message\": \"The provider operation could not finish; refresh its status before retrying\"\n  }\n}"
            },
            {
              "name": "409 — the quote expired",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}/purchase",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}",
                    "purchase"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"accept_terms\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The number/account is already connected or the configuration version changed; refresh before retrying\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List rentals",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/rentals",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "rentals"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Your purchases and their renewal dates (quotes are left out). `state` is `active` once a purchase finishes. `reserved` or `purchasing` means it's still going: send the purchase again to finish it. `failed` means it didn't complete and any money held for it has been returned (`release_reason`). `releasing` and `released` are the end of a rental. `renews_at` is the next ₹1,500 charge for a Mirai rental. Up to 100 per page."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals"
                  ],
                  "query": [
                    {
                      "key": "cursor",
                      "value": "rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9\",\n      \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n      \"number\": \"+912248901234\",\n      \"ownership\": \"managed\",\n      \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n      \"number_type\": \"local\",\n      \"provider_monthly_rate\": \"2.50000\",\n      \"provider_setup_rate\": \"0.00000\",\n      \"state\": \"active\",\n      \"phone_number_id\": \"phn_01K9R1B3D5F7H9K2M4P6R8T0W2\",\n      \"amount_paise\": 150000,\n      \"term_months\": 3,\n      \"expires_at\": \"2026-10-09T06:20:02.418356Z\",\n      \"purchased_at\": \"2026-10-09T06:12:44.120537Z\",\n      \"renews_at\": \"2027-01-09T06:12:44.120537Z\",\n      \"cancel_at_period_end\": false,\n      \"release_reason\": \"\",\n      \"created_at\": \"2026-10-09T06:10:02.418356Z\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Get rental",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "rentals",
                "{{rental_id}}"
              ]
            },
            "description": "One quote or rental, by its id. A quote stays readable after it expires."
          },
          "response": [
            {
              "name": "200 — an active rental",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9\",\n  \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n  \"number\": \"+912248901234\",\n  \"ownership\": \"managed\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"number_type\": \"local\",\n  \"provider_monthly_rate\": \"2.50000\",\n  \"provider_setup_rate\": \"0.00000\",\n  \"state\": \"active\",\n  \"phone_number_id\": \"phn_01K9R1B3D5F7H9K2M4P6R8T0W2\",\n  \"amount_paise\": 150000,\n  \"term_months\": 3,\n  \"expires_at\": \"2026-10-09T06:20:02.418356Z\",\n  \"purchased_at\": \"2026-10-09T06:12:44.120537Z\",\n  \"renews_at\": \"2027-01-09T06:12:44.120537Z\",\n  \"cancel_at_period_end\": false,\n  \"release_reason\": \"\",\n  \"created_at\": \"2026-10-09T06:10:02.418356Z\"\n}"
            },
            {
              "name": "200 — a quote",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9\",\n  \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n  \"number\": \"+912248901234\",\n  \"ownership\": \"managed\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"number_type\": \"local\",\n  \"provider_monthly_rate\": \"2.50000\",\n  \"provider_setup_rate\": \"0.00000\",\n  \"state\": \"quoted\",\n  \"phone_number_id\": \"\",\n  \"amount_paise\": 150000,\n  \"term_months\": 3,\n  \"expires_at\": \"2026-10-09T06:20:02.418356Z\",\n  \"purchased_at\": null,\n  \"renews_at\": null,\n  \"cancel_at_period_end\": false,\n  \"release_reason\": \"\",\n  \"created_at\": \"2026-10-09T06:10:02.418356Z\"\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Change auto-renewal",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "rentals",
                "{{rental_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"cancel_at_period_end\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "For Mirai rentals. `cancel_at_period_end: true` stops renewal: the number keeps working until `renews_at`, then it's released and may not be available again. `false` turns renewal back on. Either works any time before the term ends.\n\nNumbers rented through your own Plivo account renew and are released in Plivo."
          },
          "response": [
            {
              "name": "200 — renewal off",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"cancel_at_period_end\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9\",\n  \"connection_id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n  \"number\": \"+912248901234\",\n  \"ownership\": \"managed\",\n  \"compliance_id\": \"4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17\",\n  \"number_type\": \"local\",\n  \"provider_monthly_rate\": \"2.50000\",\n  \"provider_setup_rate\": \"0.00000\",\n  \"state\": \"active\",\n  \"phone_number_id\": \"phn_01K9R1B3D5F7H9K2M4P6R8T0W2\",\n  \"amount_paise\": 150000,\n  \"term_months\": 3,\n  \"expires_at\": \"2026-10-09T06:20:02.418356Z\",\n  \"purchased_at\": \"2026-10-09T06:12:44.120537Z\",\n  \"renews_at\": \"2027-01-09T06:12:44.120537Z\",\n  \"cancel_at_period_end\": true,\n  \"release_reason\": \"\",\n  \"created_at\": \"2026-10-09T06:10:02.418356Z\"\n}"
            },
            {
              "name": "404 — not an active Mirai rental",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/rentals/{{rental_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "rentals",
                    "{{rental_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"cancel_at_period_end\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Connect your Plivo account",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"provider\": \"plivo\",\n  \"name\": \"Main Plivo account\",\n  \"auth_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"auth_token\": \"REPLACE_WITH_YOUR_PLIVO_AUTH_TOKEN\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Connects a Plivo account with its Auth ID and Auth Token (both on the overview page of the Plivo console). We check them with Plivo before saving. The token is encrypted and never shown again. Connecting the same account again with the same token returns the connection you already have.\n\nA subaccount can import the numbers it owns. Renting new numbers needs the main account (its Auth ID starts with `MA`). `provider` is `plivo`."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const connection_id = pick(\"id\");",
                  "  if (connection_id != null && connection_id !== '') pm.collectionVariables.set(\"connection_id\", String(connection_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — connected",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"provider\": \"plivo\",\n  \"name\": \"Main Plivo account\",\n  \"auth_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"auth_token\": \"REPLACE_WITH_YOUR_PLIVO_AUTH_TOKEN\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"name\": \"Main Plivo account\",\n  \"state\": \"verified\",\n  \"version\": 1,\n  \"created_at\": \"2026-10-09T07:00:48.551062Z\"\n}"
            },
            {
              "name": "400 — Plivo refused the credentials",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"provider\": \"plivo\",\n  \"name\": \"Main Plivo account\",\n  \"auth_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"auth_token\": \"REPLACE_WITH_YOUR_PLIVO_AUTH_TOKEN\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_credentials\",\n    \"message\": \"Plivo credentials are invalid or lack access\"\n  }\n}"
            },
            {
              "name": "409 — already connected elsewhere",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"provider\": \"plivo\",\n  \"name\": \"Main Plivo account\",\n  \"auth_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"auth_token\": \"REPLACE_WITH_YOUR_PLIVO_AUTH_TOKEN\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The number/account is already connected or the configuration version changed; refresh before retrying\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List Plivo connections",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "The Plivo accounts this workspace uses. Besides the ones you connected (`ownership: customer`), it includes the account Mirai sets up for your rented numbers (`ownership: managed`), and any SIP trunk you connected (`provider: sip`). Credentials never come back. Up to 100 per page.\n\nA SIP trunk's `sip` also says what it has been doing:\n\n* `blocked_sources`: calls to one of its numbers that we turned away in the last 24 hours because they came from an IP address not in `inbound_sources`, one entry per address: `ip`, `number` (the trunk's number that was called), `calls` and `last_at`. If the address is your carrier's, add it to `inbound_sources` with *Change your SIP trunk*.\n* `activity`: `last_inbound` and `last_outbound`, each `null` until there is one, else `at`, `call_id` (`null` for a call in to a number you haven't added), `number` (the number dialled: yours for a call in, the person called for a call out) and `result`: `answered`, `not_answered` or `failed`. `reason_code` is `null` when answered, else `busy`, `no_answer`, `declined`, `carrier_refused`, `number_not_found`, `carrier_unreachable`, `refused_by_us` or `other`. `last_outbound` also has `sip_status`, what your carrier answered (403 when it refused the call)."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ],
                  "query": [
                    {
                      "key": "cursor",
                      "value": "tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"tcn_01K9P7XG3M5N8Q1R4T6V9W2Y4Z\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"managed\",\n      \"account_id\": \"SAXXXXXXXXXXXXXXXXXX\",\n      \"name\": \"Mirai dedicated numbers\",\n      \"state\": \"verified\",\n      \"version\": 1,\n      \"created_at\": \"2026-10-05T10:02:37.009417Z\"\n    },\n    {\n      \"id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n      \"provider\": \"plivo\",\n      \"ownership\": \"customer\",\n      \"account_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n      \"name\": \"Main Plivo account\",\n      \"state\": \"verified\",\n      \"version\": 1,\n      \"created_at\": \"2026-10-09T07:00:48.551062Z\"\n    },\n    {\n      \"id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n      \"provider\": \"sip\",\n      \"ownership\": \"customer\",\n      \"account_id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n      \"name\": \"Office SIP trunk\",\n      \"state\": \"verified\",\n      \"version\": 1,\n      \"created_at\": \"2026-11-02T09:14:05.118204Z\",\n      \"sip\": {\n        \"host\": \"sip.carrier.example\",\n        \"port\": 5060,\n        \"transport\": \"udp\",\n        \"username\": \"mirai-office\",\n        \"from_domain\": \"\",\n        \"number_format\": \"national\",\n        \"dial_prefix\": \"\",\n        \"send_pai\": false,\n        \"inbound_sources\": [\n          \"203.0.113.10/32\",\n          \"198.51.100.0/28\"\n        ],\n        \"has_password\": true,\n        \"blocked_sources\": [],\n        \"activity\": {\n          \"last_inbound\": null,\n          \"last_outbound\": null\n        }\n      }\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Get Plivo connection",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections",
                "{{connection_id}}"
              ]
            },
            "description": "One connection, without its credentials. `state` is `verified` (in use) or `disabled`; `version` is what *Disable Plivo connection* needs. A SIP trunk also carries `sip`, its settings, with `has_password` instead of the password.\n\nA SIP trunk's `sip` also says what it has been doing:\n\n* `blocked_sources`: calls to one of its numbers that we turned away in the last 24 hours because they came from an IP address not in `inbound_sources`, one entry per address: `ip`, `number` (the trunk's number that was called), `calls` and `last_at`. If the address is your carrier's, add it to `inbound_sources` with *Change your SIP trunk*.\n* `activity`: `last_inbound` and `last_outbound`, each `null` until there is one, else `at`, `call_id` (`null` for a call in to a number you haven't added), `number` (the number dialled: yours for a call in, the person called for a call out) and `result`: `answered`, `not_answered` or `failed`. `reason_code` is `null` when answered, else `busy`, `no_answer`, `declined`, `carrier_refused`, `number_not_found`, `carrier_unreachable`, `refused_by_us` or `other`. `last_outbound` also has `sip_status`, what your carrier answered (403 when it refused the call)."
          },
          "response": [
            {
              "name": "200 — connected",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"name\": \"Main Plivo account\",\n  \"state\": \"verified\",\n  \"version\": 1,\n  \"created_at\": \"2026-10-09T07:00:48.551062Z\"\n}"
            },
            {
              "name": "200 — a SIP trunk",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"provider\": \"sip\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"name\": \"Office SIP trunk\",\n  \"state\": \"verified\",\n  \"version\": 1,\n  \"created_at\": \"2026-11-02T09:14:05.118204Z\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"username\": \"mirai-office\",\n    \"from_domain\": \"\",\n    \"number_format\": \"national\",\n    \"dial_prefix\": \"\",\n    \"send_pai\": false,\n    \"inbound_sources\": [\n      \"203.0.113.10/32\",\n      \"198.51.100.0/28\"\n    ],\n    \"has_password\": true,\n    \"blocked_sources\": [],\n    \"activity\": {\n      \"last_inbound\": null,\n      \"last_outbound\": null\n    }\n  }\n}"
            },
            {
              "name": "200 — a SIP trunk after a few test calls",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"provider\": \"sip\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"name\": \"Office SIP trunk\",\n  \"state\": \"verified\",\n  \"version\": 1,\n  \"created_at\": \"2026-11-02T09:14:05.118204Z\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"username\": \"mirai-office\",\n    \"from_domain\": \"\",\n    \"number_format\": \"national\",\n    \"dial_prefix\": \"\",\n    \"send_pai\": false,\n    \"inbound_sources\": [\n      \"203.0.113.10/32\",\n      \"198.51.100.0/28\"\n    ],\n    \"has_password\": true,\n    \"blocked_sources\": [\n      {\n        \"ip\": \"18.214.109.140\",\n        \"number\": \"+918045671234\",\n        \"calls\": 4,\n        \"last_at\": \"2026-11-03T09:41:07Z\"\n      }\n    ],\n    \"activity\": {\n      \"last_inbound\": {\n        \"at\": \"2026-11-03T09:52:30Z\",\n        \"call_id\": \"call_01M6G2C8Q7ZK9W1V3X5Y7B9D1F\",\n        \"number\": \"+918045671234\",\n        \"result\": \"answered\",\n        \"reason_code\": null\n      },\n      \"last_outbound\": {\n        \"at\": \"2026-11-03T09:58:12Z\",\n        \"call_id\": \"call_01M6G2K4T2XN8R6P4M2J0H8G6E\",\n        \"number\": \"+919876543210\",\n        \"result\": \"failed\",\n        \"reason_code\": \"carrier_refused\",\n        \"sip_status\": 403\n      }\n    }\n  }\n}"
            },
            {
              "name": "404 — not in this workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Provider connection or number not found\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List numbers in your Plivo account",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/numbers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections",
                "{{connection_id}}",
                "numbers"
              ],
              "query": [
                {
                  "key": "cursor",
                  "value": "20",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "The voice numbers this Plivo account owns, 20 at a time. Read-only: nothing changes in Plivo. Bring one over with *Phone numbers → Import a Plivo number*.\n\n`application` is the voice routing a number already has in Plivo; turning on incoming calls later replaces it, only if you confirm. A number with `sms_enabled` or `mms_enabled` can be imported but not turned on for calls."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const plivo_number = pick(\"data.0.number\");",
                  "  if (plivo_number != null && plivo_number !== '') pm.collectionVariables.set(\"plivo_number\", String(plivo_number));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}",
                    "numbers"
                  ],
                  "query": [
                    {
                      "key": "cursor",
                      "value": "20",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"number\": \"+918048123456\",\n      \"voice_enabled\": true,\n      \"sms_enabled\": false,\n      \"mms_enabled\": false,\n      \"application\": \"/v1/Account/MAXXXXXXXXXXXXXXXXXX/Application/29871234567890123/\",\n      \"region\": \"Karnataka, INDIA\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            },
            {
              "name": "409 — the connection is disabled",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}",
                    "numbers"
                  ],
                  "query": [
                    {
                      "key": "cursor",
                      "value": "20",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_ready\",\n    \"message\": \"Verify the connection and activate the number before calling\"\n  }\n}"
            },
            {
              "name": "400 — a SIP trunk has no number list",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/numbers",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}",
                    "numbers"
                  ],
                  "query": [
                    {
                      "key": "cursor",
                      "value": "20",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_supported\",\n    \"message\": \"A SIP trunk has no number list; add its numbers by number\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Disable Plivo connection",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections",
                "{{connection_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": 1,\n  \"state\": \"disabled\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Stops new calls through this Plivo account (or SIP trunk); calls already running finish normally. `state` must be `disabled` and `version` the connection's current one. To turn it back on, use *Verify Plivo connection*."
          },
          "response": [
            {
              "name": "200 — disabled",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"state\": \"disabled\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"name\": \"Main Plivo account\",\n  \"state\": \"disabled\",\n  \"version\": 2,\n  \"created_at\": \"2026-10-09T07:00:48.551062Z\"\n}"
            },
            {
              "name": "409 — stale version",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"state\": \"disabled\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The number/account is already connected or the configuration version changed; refresh before retrying\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Verify Plivo connection",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/verify",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections",
                "{{connection_id}}",
                "verify"
              ]
            },
            "description": "Checks the saved credentials with Plivo again and, if they still work, turns the connection on. Use it to re-enable a disabled connection. On a SIP trunk there is nothing to check with a provider: it turns the trunk back on. No body."
          },
          "response": [
            {
              "name": "200 — on again",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/verify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}",
                    "verify"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW\",\n  \"provider\": \"plivo\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"MAXXXXXXXXXXXXXXXXXX\",\n  \"name\": \"Main Plivo account\",\n  \"state\": \"verified\",\n  \"version\": 3,\n  \"created_at\": \"2026-10-09T07:00:48.551062Z\"\n}"
            },
            {
              "name": "400 — Plivo no longer accepts the credentials",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{connection_id}}/verify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{connection_id}}",
                    "verify"
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_credentials\",\n    \"message\": \"Plivo credentials are invalid or lack access\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Connect your SIP trunk",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"provider\": \"sip\",\n  \"name\": \"Office SIP trunk\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"number_format\": \"national\",\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"198.51.100.0/28\"\n    ],\n    \"username\": \"mirai-office\",\n    \"password\": \"REPLACE_WITH_YOUR_TRUNK_PASSWORD\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Connects your own SIP trunk, when *Get number options* lists `sip` for your workspace (otherwise 400 `provider_unavailable`). Nothing is checked with your carrier: the trunk is `verified` at once. Then give your carrier the details in `sip` from *Get number options*, and add the trunk's numbers with *Phone numbers → Add a number on your SIP trunk*.\n\nIn `sip`:\n\n* `host`: your carrier's SIP address, a host name or a public IPv4 address (not a private, loopback, link-local or multicast one, and not ours). `port` 1–65535, default 5060. `transport` is `udp` or `tcp`.\n* `inbound_sources` (required): the 1–16 public IPv4 addresses or ranges your carrier calls from, each /24 or narrower; a bare address means /32. We only answer calls from these.\n* `number_format`: how we write numbers on calls to your carrier: `e164` (+919876543210), `e164_digits` (919876543210), `national` (09876543210) or `local` (9876543210).\n* `dial_prefix`: only if your carrier gave you a tech prefix (some Indian carriers route calls on one). Digits only, up to 12. We put it before every number we dial, written as `number_format` says: `45454` with `e164_digits` dials `45454919876543210`. Leave it out or send `\"\"` for none; a trunk without one reads back `\"\"`.\n* `username` and `password`: only if your carrier asks our calls to sign in (digest). The password is encrypted and never shown again.\n* `from_domain` (defaults to `host`) and `send_pai` (adds a P-Asserted-Identity header): only if your carrier asks for them.\n\nCalls on your trunk's numbers carry no Mirai line charge; your carrier bills you for the line. India numbers only."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const sip_connection_id = pick(\"id\");",
                  "  if (sip_connection_id != null && sip_connection_id !== '') pm.collectionVariables.set(\"sip_connection_id\", String(sip_connection_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — connected",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"provider\": \"sip\",\n  \"name\": \"Office SIP trunk\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"number_format\": \"national\",\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"198.51.100.0/28\"\n    ],\n    \"username\": \"mirai-office\",\n    \"password\": \"REPLACE_WITH_YOUR_TRUNK_PASSWORD\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"provider\": \"sip\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"name\": \"Office SIP trunk\",\n  \"state\": \"verified\",\n  \"version\": 1,\n  \"created_at\": \"2026-11-02T09:14:05.118204Z\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"username\": \"mirai-office\",\n    \"from_domain\": \"\",\n    \"number_format\": \"national\",\n    \"dial_prefix\": \"\",\n    \"send_pai\": false,\n    \"inbound_sources\": [\n      \"203.0.113.10/32\",\n      \"198.51.100.0/28\"\n    ],\n    \"has_password\": true,\n    \"blocked_sources\": [],\n    \"activity\": {\n      \"last_inbound\": null,\n      \"last_outbound\": null\n    }\n  }\n}"
            },
            {
              "name": "400 — a private carrier address",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"provider\": \"sip\",\n  \"name\": \"Office SIP trunk\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"number_format\": \"national\",\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"198.51.100.0/28\"\n    ],\n    \"username\": \"mirai-office\",\n    \"password\": \"REPLACE_WITH_YOUR_TRUNK_PASSWORD\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"sip.host must be a public address\"\n  }\n}"
            },
            {
              "name": "400 — SIP trunks aren't on for this workspace",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"provider\": \"sip\",\n  \"name\": \"Office SIP trunk\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"number_format\": \"national\",\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"198.51.100.0/28\"\n    ],\n    \"username\": \"mirai-office\",\n    \"password\": \"REPLACE_WITH_YOUR_TRUNK_PASSWORD\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"provider_unavailable\",\n    \"message\": \"SIP trunks are not available for this workspace\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Change your SIP trunk",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/connections/{{sip_connection_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "connections",
                "{{sip_connection_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"version\": 1,\n  \"sip\": {\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"203.0.113.11\"\n    ],\n    \"number_format\": \"e164\",\n    \"dial_prefix\": \"45454\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Changes a SIP trunk's settings. Send its current `version` and, in `sip`, only the fields that change; the rest stay as they are. Leave `password` out to keep the saved one, send a new one to replace it, or send `null` to remove it. `dial_prefix` works the same way: leave it out to keep it, send digits to replace it, or send `\"\"` to remove it. `state: disabled` still turns the trunk off, as for a Plivo account. Changes apply from the next call.\n\nTo take calls from an address in `blocked_sources`, send `inbound_sources` as the list the trunk has plus that address (a bare address means /32), as the example does."
          },
          "response": [
            {
              "name": "200 — changed",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{sip_connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{sip_connection_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"sip\": {\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"203.0.113.11\"\n    ],\n    \"number_format\": \"e164\",\n    \"dial_prefix\": \"45454\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"provider\": \"sip\",\n  \"ownership\": \"customer\",\n  \"account_id\": \"tcn_01K9S3X6E9G4J7K0MPQRSTVWXY\",\n  \"name\": \"Office SIP trunk\",\n  \"state\": \"verified\",\n  \"version\": 2,\n  \"created_at\": \"2026-11-02T09:14:05.118204Z\",\n  \"sip\": {\n    \"host\": \"sip.carrier.example\",\n    \"port\": 5060,\n    \"transport\": \"udp\",\n    \"username\": \"mirai-office\",\n    \"from_domain\": \"\",\n    \"number_format\": \"e164\",\n    \"dial_prefix\": \"45454\",\n    \"send_pai\": false,\n    \"inbound_sources\": [\n      \"203.0.113.10/32\",\n      \"203.0.113.11/32\"\n    ],\n    \"has_password\": true,\n    \"blocked_sources\": [],\n    \"activity\": {\n      \"last_inbound\": null,\n      \"last_outbound\": null\n    }\n  }\n}"
            },
            {
              "name": "409 — stale version",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/connections/{{sip_connection_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "connections",
                    "{{sip_connection_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"version\": 1,\n  \"sip\": {\n    \"inbound_sources\": [\n      \"203.0.113.10\",\n      \"203.0.113.11\"\n    ],\n    \"number_format\": \"e164\",\n    \"dial_prefix\": \"45454\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"conflict\",\n    \"message\": \"The number/account is already connected or the configuration version changed; refresh before retrying\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Send a verification call",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/phone-verifications",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "phone-verifications"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"{{test_number}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "**This places a real phone call** to `phone` (an Indian `+91` number) that reads out a code. Once verified, the workspace can ring that phone from Mirai's shared test number for 30 days. The code is good for ten minutes. One call a minute per workspace, and per phone.\n\nA deployment without a shared test number answers `503 shared_test_unavailable` and calls no one. Place calls from the shared line or from a number of your own instead."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const verification_id = pick(\"id\");",
                  "  if (verification_id != null && verification_id !== '') pm.collectionVariables.set(\"verification_id\", String(verification_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — calling you now",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"{{test_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"channel\": \"voice\",\n  \"expires_in_secs\": 600,\n  \"id\": \"verify_01K9Q5C9E4G6J8M1P3R5T7X9Z1\",\n  \"phone\": \"+919876543210\"\n}"
            },
            {
              "name": "429 — wait a minute",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"{{test_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Retry-After",
                  "value": "60"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"rate_limited\",\n    \"message\": \"Wait one minute before requesting another verification call\"\n  }\n}"
            },
            {
              "name": "400 — not an Indian number",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"{{test_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Enter an Indian phone number in +91 format\"\n  }\n}"
            },
            {
              "name": "503 — no shared test number here",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"phone\": \"{{test_number}}\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"shared_test_unavailable\",\n    \"message\": \"The shared test number is not available on this deployment\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Check the verification code",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/telephony/phone-verifications/{{verification_id}}/verify",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "telephony",
                "phone-verifications",
                "{{verification_id}}",
                "verify"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"code\": \"123456\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Send the code you heard on the verification call (replace the example). Five tries per call; after that, ask for a new call."
          },
          "response": [
            {
              "name": "200 — verified",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications/{{verification_id}}/verify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications",
                    "{{verification_id}}",
                    "verify"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"code\": \"123456\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"phone\": \"+919876543210\",\n  \"verified\": true\n}"
            },
            {
              "name": "400 — wrong code",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications/{{verification_id}}/verify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications",
                    "{{verification_id}}",
                    "verify"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"code\": \"123456\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"verification_failed\",\n    \"message\": \"The code could not be verified; check it and try again\"\n  }\n}"
            },
            {
              "name": "404 — code expired",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications/{{verification_id}}/verify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications",
                    "{{verification_id}}",
                    "verify"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"code\": \"123456\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"Verification expired; request a new code\"\n  }\n}"
            },
            {
              "name": "503 — no shared test number here",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/telephony/phone-verifications/{{verification_id}}/verify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "telephony",
                    "phone-verifications",
                    "{{verification_id}}",
                    "verify"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"code\": \"123456\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"shared_test_unavailable\",\n    \"message\": \"The shared test number is not available on this deployment\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Transcriptions",
      "description": "Turn a recorded call (or any recording) into a transcript with speakers and timestamps. Hindi, English, Gujarati and mixed speech are written the way they were spoken, never translated. ₹18 per hour of audio; failed and degraded jobs are free.",
      "item": [
        {
          "name": "Create a transcription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "call-2026-10-02-0412",
                "description": "Up to 255 characters, from your own records."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/transcriptions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "transcriptions"
              ]
            },
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": [],
                  "description": "The recording. One file per request."
                },
                {
                  "key": "context",
                  "type": "text",
                  "value": "A call to a university admissions desk about a course and its fees",
                  "description": "Who is calling whom and why. Up to 2,000 characters."
                },
                {
                  "key": "vocabulary",
                  "type": "text",
                  "value": "Mira University, BBA, Aadhaar",
                  "description": "Names and terms to spell right, comma or newline separated."
                },
                {
                  "key": "language",
                  "type": "text",
                  "value": "auto",
                  "description": "auto (default), hi, gu, en, mr, pa, bn or ur.",
                  "disabled": true
                },
                {
                  "key": "diarize",
                  "type": "text",
                  "value": "true",
                  "description": "Speaker separation. Default true.",
                  "disabled": true
                },
                {
                  "key": "words",
                  "type": "text",
                  "value": "false",
                  "description": "Word timings on each segment. Default false.",
                  "disabled": true
                }
              ]
            },
            "description": "Upload a recording (up to 45 MB, up to two hours, any common audio format) and get a job back straight away with `202`. Then read it with *Get a transcription* until `status` is `completed` or `failed`.\n\nPick the file in the `file` field before you send. `context` and `vocabulary` are optional but help a lot with names and brand terms.\n\nPrefer to send a link? Switch the body to raw JSON with an `https` `url` (up to 200 MB) instead of `file`; every other field is the same.\n\nThe `Idempotency-Key` makes a retry safe: the same key returns the job it already created, with no second charge."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const transcription_id = pick(\"id\");",
                  "  if (transcription_id != null && transcription_id !== '') pm.collectionVariables.set(\"transcription_id\", String(transcription_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "202 — accepted",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Idempotency-Key",
                    "value": "call-2026-10-02-0412",
                    "description": "Up to 255 characters, from your own records."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "context",
                      "type": "text",
                      "value": "A call to a university admissions desk about a course and its fees",
                      "description": "Who is calling whom and why. Up to 2,000 characters."
                    },
                    {
                      "key": "vocabulary",
                      "type": "text",
                      "value": "Mira University, BBA, Aadhaar",
                      "description": "Names and terms to spell right, comma or newline separated."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "auto",
                      "description": "auto (default), hi, gu, en, mr, pa, bn or ur.",
                      "disabled": true
                    },
                    {
                      "key": "diarize",
                      "type": "text",
                      "value": "true",
                      "description": "Speaker separation. Default true.",
                      "disabled": true
                    },
                    {
                      "key": "words",
                      "type": "text",
                      "value": "false",
                      "description": "Word timings on each segment. Default false.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Location",
                  "value": "/v2/transcriptions/trn_01M3XRSFXW77RHEQ85979AJXAF"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"trn_01M3XRSFXW77RHEQ85979AJXAF\",\n  \"object\": \"transcription\",\n  \"status\": \"queued\",\n  \"created_at\": \"2026-10-02T07:38:20Z\",\n  \"finished_at\": null,\n  \"duration_s\": null,\n  \"degraded\": null,\n  \"model\": null,\n  \"source\": \"upload\",\n  \"file_name\": \"call.wav\",\n  \"bytes\": 370308,\n  \"language\": null,\n  \"diarize\": true,\n  \"words\": false,\n  \"error\": null,\n  \"cost\": {\n    \"status\": \"pending\",\n    \"amount_inr\": null,\n    \"rate_inr_per_hour\": 18\n  }\n}"
            },
            {
              "name": "402 — the wallet is empty",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Idempotency-Key",
                    "value": "call-2026-10-02-0412",
                    "description": "Up to 255 characters, from your own records."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "context",
                      "type": "text",
                      "value": "A call to a university admissions desk about a course and its fees",
                      "description": "Who is calling whom and why. Up to 2,000 characters."
                    },
                    {
                      "key": "vocabulary",
                      "type": "text",
                      "value": "Mira University, BBA, Aadhaar",
                      "description": "Names and terms to spell right, comma or newline separated."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "auto",
                      "description": "auto (default), hi, gu, en, mr, pa, bn or ur.",
                      "disabled": true
                    },
                    {
                      "key": "diarize",
                      "type": "text",
                      "value": "true",
                      "description": "Speaker separation. Default true.",
                      "disabled": true
                    },
                    {
                      "key": "words",
                      "type": "text",
                      "value": "false",
                      "description": "Word timings on each segment. Default false.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance 0.00 INR is empty; transcribing a recording needs a positive balance\"\n  }\n}"
            },
            {
              "name": "429 — 20 jobs already running",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Idempotency-Key",
                    "value": "call-2026-10-02-0412",
                    "description": "Up to 255 characters, from your own records."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "context",
                      "type": "text",
                      "value": "A call to a university admissions desk about a course and its fees",
                      "description": "Who is calling whom and why. Up to 2,000 characters."
                    },
                    {
                      "key": "vocabulary",
                      "type": "text",
                      "value": "Mira University, BBA, Aadhaar",
                      "description": "Names and terms to spell right, comma or newline separated."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "auto",
                      "description": "auto (default), hi, gu, en, mr, pa, bn or ur.",
                      "disabled": true
                    },
                    {
                      "key": "diarize",
                      "type": "text",
                      "value": "true",
                      "description": "Speaker separation. Default true.",
                      "disabled": true
                    },
                    {
                      "key": "words",
                      "type": "text",
                      "value": "false",
                      "description": "Word timings on each segment. Default false.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Retry-After",
                  "value": "30"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"at_capacity\",\n    \"message\": \"this workspace already has 20 transcriptions in progress (the limit is 20); retry when one finishes\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get a transcription",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/transcriptions/{{transcription_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "transcriptions",
                "{{transcription_id}}"
              ]
            },
            "description": "Read a job until it finishes. Short recordings often complete in seconds, so poll quickly at first and then every few seconds. While the job is `merging` it carries a provisional `draft`; once `completed` it has `text`, `segments` and `diarization`.\n\nCopy finished transcripts into your own storage: they are not kept forever."
          },
          "response": [
            {
              "name": "200 — completed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions/{{transcription_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions",
                    "{{transcription_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"trn_01M3XRSFXW77RHEQ85979AJXAF\",\n  \"object\": \"transcription\",\n  \"status\": \"completed\",\n  \"created_at\": \"2026-10-02T07:38:20Z\",\n  \"finished_at\": \"2026-10-02T07:38:26Z\",\n  \"duration_s\": 23.14,\n  \"degraded\": false,\n  \"model\": \"mira-transcribe-offline-1\",\n  \"source\": \"upload\",\n  \"file_name\": \"call.wav\",\n  \"bytes\": 370308,\n  \"language\": null,\n  \"diarize\": true,\n  \"words\": false,\n  \"error\": null,\n  \"cost\": {\n    \"status\": \"charged\",\n    \"amount_inr\": 0.12,\n    \"rate_inr_per_hour\": 18\n  },\n  \"text\": \"नमस्ते मैं Mira University के admissions desk से बात कर रही हूँ क्या आपके पास दो मिनट हैं yes tell me I wanted to ask about the BBA course fees जी ज़रूर BBA की fees एक लाख बीस हज़ार रुपये प्रति वर्ष है okay thank you\",\n  \"segments\": [\n    {\n      \"speaker\": \"Agent\",\n      \"speaker_id\": \"spk0\",\n      \"start\": 0,\n      \"end\": 6.57,\n      \"text\": \"नमस्ते मैं Mira University के admissions desk से बात कर रही हूँ क्या आपके पास दो मिनट हैं\"\n    },\n    {\n      \"speaker\": \"Customer\",\n      \"speaker_id\": \"spk1\",\n      \"start\": 7.21,\n      \"end\": 11.32,\n      \"text\": \"yes tell me I wanted to ask about the BBA course fees\"\n    },\n    {\n      \"speaker\": \"Agent\",\n      \"speaker_id\": \"spk0\",\n      \"start\": 11.98,\n      \"end\": 19.56,\n      \"text\": \"जी ज़रूर BBA की fees एक लाख बीस हज़ार रुपये प्रति वर्ष है\"\n    },\n    {\n      \"speaker\": \"Customer\",\n      \"speaker_id\": \"spk1\",\n      \"start\": 20.21,\n      \"end\": 23.05,\n      \"text\": \"okay thank you\"\n    }\n  ],\n  \"diarization\": {\n    \"enabled\": true,\n    \"applied\": true,\n    \"speakers\": [\n      {\n        \"id\": \"spk0\",\n        \"role\": \"Agent\",\n        \"talk_s\": 14.1\n      },\n      {\n        \"id\": \"spk1\",\n        \"role\": \"Customer\",\n        \"talk_s\": 7\n      }\n    ]\n  }\n}"
            },
            {
              "name": "200 — failed",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions/{{transcription_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions",
                    "{{transcription_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"trn_01M3XS0Q2B7K9D4F6H8J1M3N5P\",\n  \"object\": \"transcription\",\n  \"status\": \"failed\",\n  \"created_at\": \"2026-10-02T07:38:20Z\",\n  \"finished_at\": \"2026-10-02T07:40:02Z\",\n  \"duration_s\": null,\n  \"degraded\": null,\n  \"model\": null,\n  \"source\": \"upload\",\n  \"file_name\": \"call.wav\",\n  \"bytes\": 370308,\n  \"language\": null,\n  \"diarize\": true,\n  \"words\": false,\n  \"error\": {\n    \"code\": \"audio_too_long\",\n    \"message\": \"the recording is longer than 120 minutes, the most one job takes\"\n  },\n  \"cost\": {\n    \"status\": \"free\",\n    \"amount_inr\": 0,\n    \"rate_inr_per_hour\": 18\n  }\n}"
            },
            {
              "name": "404 — not in your workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions/{{transcription_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions",
                    "{{transcription_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no transcription trn_01M3XRSFXW77RHEQ85979AJXAF\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List transcriptions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/transcriptions?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "transcriptions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100."
                },
                {
                  "key": "status",
                  "value": "completed",
                  "description": "queued, decoding, merging, completed or failed.",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "`next_cursor` from the previous page.",
                  "disabled": true
                }
              ]
            },
            "description": "Your workspace's jobs, newest first, including ones started from the console. List rows leave out the transcript itself; read a job by id for that."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/transcriptions?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "transcriptions"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100."
                    },
                    {
                      "key": "status",
                      "value": "completed",
                      "description": "queued, decoding, merging, completed or failed.",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "`next_cursor` from the previous page.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"trn_01M3XRSFXW77RHEQ85979AJXAF\",\n      \"object\": \"transcription\",\n      \"status\": \"completed\",\n      \"created_at\": \"2026-10-02T07:38:20Z\",\n      \"finished_at\": \"2026-10-02T07:38:26Z\",\n      \"duration_s\": 23.14,\n      \"degraded\": false,\n      \"model\": \"mira-transcribe-offline-1\",\n      \"source\": \"upload\",\n      \"file_name\": \"call.wav\",\n      \"bytes\": 370308,\n      \"language\": null,\n      \"diarize\": true,\n      \"words\": false,\n      \"error\": null,\n      \"cost\": {\n        \"status\": \"charged\",\n        \"amount_inr\": 0.12,\n        \"rate_inr_per_hour\": 18\n      }\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Speech to text",
      "description": "Speech to text in ten languages, two ways: send one recording and get its text back in the same request (*Transcribe a recording*), or stream live audio over one WebSocket per call and read partial transcripts while people speak, then one final transcript per utterance. Language codes: hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN.\n\n**The socket is not a request in this folder.** Open it with a WebSocket client (Postman's own WebSocket request works) at\n\n`wss://sandbox.voice.miraiminds.co/v1/audio/transcriptions/stream?language_code=hi-IN&encoding=mulaw&sample_rate=8000&endpointing=manual`\n\n(`wss://prod.voice.miraiminds.co` once your company has gone live), with the header `Authorization: Bearer {{api_key}}`. 8 or 16 kHz, 16-bit PCM, μ-law or A-law. A browser uses `?token=` from *Mint stream tokens* instead, because it cannot set headers on a WebSocket.\n\nSend JSON text frames: `{\"event\": \"speech_start\"}`, then `{\"event\": \"audio_input\", \"audio\": \"<base64 audio>\"}` as the audio arrives, then `{\"event\": \"speech_end\"}`; `{\"event\": \"end\"}` closes the session. You receive `session.begin` first, `transcript.partial` while an utterance is open, exactly one `transcript.final` per utterance, and `session.end` with `audio_seconds_billed` and `cost_paise`.\n\nEvery event, both endpointing modes, limits and errors: https://docs.miraiminds.co/v2/stt-quickstart",
      "item": [
        {
          "name": "Transcribe a recording",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/stt",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "stt"
              ]
            },
            "body": {
              "mode": "formdata",
              "formdata": [
                {
                  "key": "file",
                  "type": "file",
                  "src": [],
                  "description": "The recording. One file per request."
                },
                {
                  "key": "model",
                  "type": "text",
                  "value": "mira-stt",
                  "description": "mira-stt."
                },
                {
                  "key": "language",
                  "type": "text",
                  "value": "hi-IN",
                  "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                },
                {
                  "key": "response_format",
                  "type": "text",
                  "value": "verbose_json",
                  "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                  "disabled": true
                }
              ]
            },
            "description": "One recording in, its text out, in the same request. This is `POST /v1/audio/transcriptions` under its v2 name: the same route, so the OpenAI SDK works against `{{base_url}}/v1` with only the key changed.\n\nUp to 25 MB and 2 minutes of audio: WAV, MP3 and most audio formats; headerless audio needs `encoding` (`linear16`, `mulaw`, `alaw`) and `sample_rate` (8000 or 16000). A longer recording is a job for *Transcriptions* (`POST /v2/transcriptions`).\n\nBilled per second of audio, rounded up, from your wallet; the answer's `X-Cost-Paise` says what it cost and `X-Request-Id` is its row in *List requests*."
          },
          "response": [
            {
              "name": "200 — the text",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "model",
                      "type": "text",
                      "value": "mira-stt",
                      "description": "mira-stt."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi-IN",
                      "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                    },
                    {
                      "key": "response_format",
                      "type": "text",
                      "value": "verbose_json",
                      "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "stt_01K7D0A2B4C6D8E0F2G4H6J8K0"
                },
                {
                  "key": "X-Audio-Seconds",
                  "value": "7"
                },
                {
                  "key": "X-Cost-Paise",
                  "value": "4"
                },
                {
                  "key": "X-Mira-Model",
                  "value": "mira-stt"
                }
              ],
              "cookie": [],
              "body": "{\n  \"text\": \"નમસ્તે, મારે કાલે સાંજે પાંચ વાગ્યાની appointment book કરાવવી છે.\"\n}"
            },
            {
              "name": "200 — verbose_json",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "model",
                      "type": "text",
                      "value": "mira-stt",
                      "description": "mira-stt."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi-IN",
                      "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                    },
                    {
                      "key": "response_format",
                      "type": "text",
                      "value": "verbose_json",
                      "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "stt_01K7D0A2B4C6D8E0F2G4H6J8K0"
                },
                {
                  "key": "X-Audio-Seconds",
                  "value": "7"
                },
                {
                  "key": "X-Cost-Paise",
                  "value": "4"
                },
                {
                  "key": "X-Mira-Model",
                  "value": "mira-stt"
                }
              ],
              "cookie": [],
              "body": "{\n  \"text\": \"हाँ जी, बोलिए। मेरा नंबर नौ आठ सात छह है।\",\n  \"language\": \"hi-IN\",\n  \"duration\": 6.4,\n  \"segments\": [\n    {\n      \"id\": 0,\n      \"start\": 0.2,\n      \"end\": 1.6,\n      \"text\": \"हाँ जी, बोलिए।\"\n    },\n    {\n      \"id\": 1,\n      \"start\": 2.3,\n      \"end\": 6.1,\n      \"text\": \"मेरा नंबर नौ आठ सात छह है।\"\n    }\n  ]\n}"
            },
            {
              "name": "400 — a language outside the ten",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "model",
                      "type": "text",
                      "value": "mira-stt",
                      "description": "mira-stt."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi-IN",
                      "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                    },
                    {
                      "key": "response_format",
                      "type": "text",
                      "value": "verbose_json",
                      "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_config\",\n    \"message\": \"language must be one of hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN, ml-IN\"\n  }\n}"
            },
            {
              "name": "413 — longer than 2 minutes",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "model",
                      "type": "text",
                      "value": "mira-stt",
                      "description": "mira-stt."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi-IN",
                      "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                    },
                    {
                      "key": "response_format",
                      "type": "text",
                      "value": "verbose_json",
                      "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Request Entity Too Large",
              "code": 413,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"audio_too_long\",\n    \"message\": \"a recording longer than 120 s goes to POST /v2/transcriptions\"\n  }\n}"
            },
            {
              "name": "402 — the wallet is empty",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "model",
                      "type": "text",
                      "value": "mira-stt",
                      "description": "mira-stt."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi-IN",
                      "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                    },
                    {
                      "key": "response_format",
                      "type": "text",
                      "value": "verbose_json",
                      "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance is 0.00 INR; top up before transcribing\"\n  }\n}"
            },
            {
              "name": "429 — too many at once",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt"
                  ]
                },
                "body": {
                  "mode": "formdata",
                  "formdata": [
                    {
                      "key": "file",
                      "type": "file",
                      "src": [],
                      "description": "The recording. One file per request."
                    },
                    {
                      "key": "model",
                      "type": "text",
                      "value": "mira-stt",
                      "description": "mira-stt."
                    },
                    {
                      "key": "language",
                      "type": "text",
                      "value": "hi-IN",
                      "description": "hi-IN, en-IN, gu-IN, mr-IN, pa-IN, bn-IN, ta-IN, te-IN, kn-IN or ml-IN (default hi-IN). The two-letter code works too."
                    },
                    {
                      "key": "response_format",
                      "type": "text",
                      "value": "verbose_json",
                      "description": "json (default, `{\"text\"}`), verbose_json (with each utterance's start and end) or text.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Retry-After",
                  "value": "2"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"at_capacity\",\n    \"message\": \"too many speech-to-text requests open for this workspace\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Mint stream tokens",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/stt/stream/tokens",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "stt",
                "stream",
                "tokens"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"count\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Single-use tokens for opening the streaming socket from a browser, which cannot set headers: connect to your API host followed by `url`, and add your query parameters after it with `&`. Each token lasts 60 seconds and opens one socket, which acts and is billed as the key that minted it. `count` asks for up to 20 at once.\n\nServer code skips this and connects with its key in the `Authorization` header. A key is never accepted in the URL."
          },
          "response": [
            {
              "name": "201 — one token",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/stt/stream/tokens",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "stream",
                    "tokens"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"count\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"stt_stream_token\",\n  \"token\": \"te1.eyJzdmMiOiJzdHQifQ.Hq3x9Zt0bL7wKc2Vn5RdQe8yUf1aJm4sPo6iTg0hBkE\",\n  \"tokens\": [\n    \"te1.eyJzdmMiOiJzdHQifQ.Hq3x9Zt0bL7wKc2Vn5RdQe8yUf1aJm4sPo6iTg0hBkE\"\n  ],\n  \"expires_at\": \"2026-10-12T05:31:00Z\",\n  \"url\": \"/v1/audio/transcriptions/stream?token=te1.eyJzdmMiOiJzdHQifQ.Hq3x9Zt0bL7wKc2Vn5RdQe8yUf1aJm4sPo6iTg0hBkE\",\n  \"edge_url\": null\n}"
            },
            {
              "name": "402 — the wallet is empty",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/stt/stream/tokens",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "stream",
                    "tokens"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"count\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"insufficient_balance\",\n    \"message\": \"wallet balance is 0.00 INR; top up before opening a speech-to-text stream\"\n  }\n}"
            },
            {
              "name": "503 — not switched on for this server",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/stt/stream/tokens",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "stream",
                    "tokens"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"count\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Service Unavailable",
              "code": 503,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"unavailable\",\n    \"message\": \"speech to text is not enabled on this server\"\n  }\n}"
            },
            {
              "name": "429 — the key's request rate",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/stt/stream/tokens",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "stream",
                    "tokens"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"count\": 1\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Retry-After",
                  "value": "1"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"rate_limited\",\n    \"message\": \"request rate limit exceeded for this key\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List requests",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/stt/requests?limit=50",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "stt",
                "requests"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50",
                  "description": "1 to 200."
                },
                {
                  "key": "from",
                  "value": "2026-10-12T00:00:00Z",
                  "description": "RFC3339. Rows created at or after this time.",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "2026-10-13T00:00:00Z",
                  "description": "RFC3339. Rows created before this time.",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "completed",
                  "description": "interim, completed or failed.",
                  "disabled": true
                },
                {
                  "key": "session_id",
                  "value": "sttws_01K7C2M3Q4R7T9V2X5Y8A1B4C7",
                  "description": "Only the rows of one session.",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "`next_cursor` from the previous page.",
                  "disabled": true
                }
              ]
            },
            "description": "Your workspace's speech-to-text requests, newest first, as they were billed: how each came in (`via`: `http` for a recording, `ws` for a stream), language, audio received and seconds billed, final transcripts, cost and how it ended. A stream longer than five minutes is billed in parts, one row each (`seq`, status `interim` while it was open), sharing `session_id`. Every row is billed whatever its status."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const stt_request_id = pick(\"data.0.id\");",
                  "  if (stt_request_id != null && stt_request_id !== '') pm.collectionVariables.set(\"stt_request_id\", String(stt_request_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt/requests?limit=50",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "requests"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "50",
                      "description": "1 to 200."
                    },
                    {
                      "key": "from",
                      "value": "2026-10-12T00:00:00Z",
                      "description": "RFC3339. Rows created at or after this time.",
                      "disabled": true
                    },
                    {
                      "key": "to",
                      "value": "2026-10-13T00:00:00Z",
                      "description": "RFC3339. Rows created before this time.",
                      "disabled": true
                    },
                    {
                      "key": "status",
                      "value": "completed",
                      "description": "interim, completed or failed.",
                      "disabled": true
                    },
                    {
                      "key": "session_id",
                      "value": "sttws_01K7C2M3Q4R7T9V2X5Y8A1B4C7",
                      "description": "Only the rows of one session.",
                      "disabled": true
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "`next_cursor` from the previous page.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"stt_01K7C2M3Q4R7T9V2X5Y8A1B4C7-1\",\n      \"object\": \"stt_request\",\n      \"session_id\": \"sttws_01K7C2M3Q4R7T9V2X5Y8A1B4C7\",\n      \"seq\": 1,\n      \"created_at\": \"2026-10-12T05:30:12Z\",\n      \"ended_at\": \"2026-10-12T05:31:00Z\",\n      \"language\": \"hi-IN\",\n      \"model\": \"mira-stt:v5-realtime\",\n      \"encoding\": \"mulaw\",\n      \"sample_rate\": 8000,\n      \"endpointing\": \"manual\",\n      \"audio_seconds\": 41.36,\n      \"billed_seconds\": 42,\n      \"utterances\": 7,\n      \"status\": \"completed\",\n      \"cost_inr\": 0.21,\n      \"error_code\": null,\n      \"via\": \"ws\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Get a request",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/stt/requests/{{stt_request_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "stt",
                "requests",
                "{{stt_request_id}}"
              ]
            },
            "description": "One row of the request log, by its `id`."
          },
          "response": [
            {
              "name": "200 — a finished stream",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt/requests/{{stt_request_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "requests",
                    "{{stt_request_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"stt_01K7C2M3Q4R7T9V2X5Y8A1B4C7-1\",\n  \"object\": \"stt_request\",\n  \"session_id\": \"sttws_01K7C2M3Q4R7T9V2X5Y8A1B4C7\",\n  \"seq\": 1,\n  \"created_at\": \"2026-10-12T05:30:12Z\",\n  \"ended_at\": \"2026-10-12T05:31:00Z\",\n  \"language\": \"hi-IN\",\n  \"model\": \"mira-stt:v5-realtime\",\n  \"encoding\": \"mulaw\",\n  \"sample_rate\": 8000,\n  \"endpointing\": \"manual\",\n  \"audio_seconds\": 41.36,\n  \"billed_seconds\": 42,\n  \"utterances\": 7,\n  \"status\": \"completed\",\n  \"cost_inr\": 0.21,\n  \"error_code\": null,\n  \"via\": \"ws\"\n}"
            },
            {
              "name": "404 — not in your workspace",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/stt/requests/{{stt_request_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "stt",
                    "requests",
                    "{{stt_request_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"not_found\",\n    \"message\": \"no stt request stt_01K7C2M3Q4R7T9V2X5Y8A1B4C7-1\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Wallet",
      "description": "Your prepaid balance and every line that moved it. Calls, text to speech, flow drafts, transcriptions and number rentals all debit the same wallet.",
      "item": [
        {
          "name": "Get wallet",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/wallet",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "wallet"
              ]
            },
            "description": "Your spendable balance in rupees. It never goes negative. Calls are billed in 10-second blocks, rounded up, and only for calls that connected.\n\nPoll it on a schedule and alert yourself below a day's worth of traffic. Finding out from a `402` in the middle of a campaign is worse."
          },
          "response": [
            {
              "name": "200 — the balance",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/wallet",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "wallet"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"balance_inr\": 191.55,\n  \"currency\": \"INR\",\n  \"updated_at\": \"2026-10-09T09:16:55Z\"\n}"
            }
          ]
        },
        {
          "name": "List wallet transactions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/wallet/transactions?limit=20",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "wallet",
                "transactions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "20",
                  "description": "1 to 100."
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "`next_cursor` from the previous page.",
                  "disabled": true
                }
              ]
            },
            "description": "The ledger, newest first, one row per credit or debit. Branch on `kind` (`call`, `tts`, `flow_generation`, `transcription`, `number_rental`, `promotion`, `monthly_minimum`) rather than on `description`, which is for people. New kinds can appear, so tolerate ones you don't know.\n\nPage with `cursor` set to the previous page's `next_cursor` until `has_more` is false."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/wallet/transactions?limit=20",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "wallet",
                    "transactions"
                  ],
                  "query": [
                    {
                      "key": "limit",
                      "value": "20",
                      "description": "1 to 100."
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "`next_cursor` from the previous page.",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"txn_01K2M4RC1DEFGHJKMNPQRS\",\n      \"object\": \"wallet_transaction\",\n      \"type\": \"debit\",\n      \"amount_inr\": 8.33,\n      \"balance_after_inr\": 191.55,\n      \"call_id\": \"call_01K2M4RB8CDEFGHJKMNPQRST\",\n      \"kind\": \"call\",\n      \"description\": \"call 96s @ t5\",\n      \"billed_seconds\": 100,\n      \"per_min_inr\": 5,\n      \"billing_block_secs\": 10,\n      \"pricing\": {\n        \"voice_rate_paise\": 500,\n        \"insights_rate_paise\": 0,\n        \"telco_rate_paise\": 0,\n        \"telco_block_seconds\": 0,\n        \"rate_paise\": 500,\n        \"block_seconds\": 10,\n        \"insights_enabled\": false\n      },\n      \"created_at\": \"2026-10-09T09:16:55Z\"\n    },\n    {\n      \"id\": \"txn_01K2M4QZ7XWVTSRQPNMKJH\",\n      \"object\": \"wallet_transaction\",\n      \"type\": \"debit\",\n      \"amount_inr\": 0.12,\n      \"balance_after_inr\": 199.88,\n      \"call_id\": null,\n      \"kind\": \"transcription\",\n      \"reference\": \"trn_01M3XRSFXW77RHEQ85979AJXAF\",\n      \"description\": \"Transcription · 23s of audio · mira-transcribe-offline-1\",\n      \"created_at\": \"2026-10-09T08:40:26Z\"\n    },\n    {\n      \"promotional_inr\": 200,\n      \"id\": \"txn_01K2M4Q1A2B3C4D5E6F7G8\",\n      \"object\": \"wallet_transaction\",\n      \"type\": \"credit\",\n      \"amount_inr\": 200,\n      \"balance_after_inr\": 200,\n      \"call_id\": null,\n      \"kind\": \"promotion\",\n      \"reference\": \"promo_sandbox_starter\",\n      \"description\": \"Promotional credit · sandbox starter\",\n      \"created_at\": \"2026-10-09T08:30:00Z\"\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Sub-workspaces",
      "description": "For partners who run calls for many brands. Each brand gets its own sub-workspace under your account, with its own agents, campaigns, calls, phone numbers, knowledge bases, tool secrets and do-not-call list. Money stays in one place: every brand spends from your account's wallet at your account's rates, and you get one invoice.\n\n**Acting as a brand.** Use your account's API key on any request in this collection and add one header:\n\n```\nMirai-Workspace: ws_6f1c0a9e2b7d4c3a8e5f9b10\n```\n\nThe value is the sub-workspace's `id` or the `external_id` you gave it. Without the header, or with your account's own id in it, the request acts on your account as it always has. `X-Workspace` and `Workspace` work too, so an integration that already sends v1's `workspace` header keeps working once your brands are set up here with their v1 workspace ids as `external_id`. If your account has no sub-workspaces, those two are ignored.\n\nA value that names none of your brands is `404 workspace_not_found`; an archived brand is `403 workspace_archived`. The header only looks among your own brands, so it can never reach someone else's workspace.\n\nCall webhooks and campaign webhooks from every brand are signed with your account's webhook secret, and requests for all your brands share your key's rate limit. `GET /v2/wallet` with the header shows the shared account balance.\n\n**Managing brands.** The requests below act on your account, so send them without the header: with one they answer `400`. Sub-workspaces are switched on per account with a limit. Ask us to turn them on for yours.",
      "item": [
        {
          "name": "Create a sub-workspace",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/workspaces",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspaces"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Adds a brand. Only `name` is required, and it must be unique among your active brands.\n\n* `external_id`: your own id for the brand, up to 128 characters and not starting with `ws_`. Unique for good: an archived brand keeps it. Brands moved from v1 use their v1 workspace id.\n* `kind`: `custom` (the default) or `shopify`.\n* `timezone`: an IANA name, `Asia/Kolkata` by default.\n* `currency`: `INR` by default.\n* `profile`: the brand's facts as a JSON object, up to 16 KB.\n\nSafe to retry. Sending an `external_id` or an active name you already have returns `409 workspace_exists` with that brand in `workspace`, so a script that lost the first answer can pick up the id and carry on."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "// Saves what this request created, so the next request in the folder uses it.",
                  "if (pm.response.code >= 200 && pm.response.code < 300) {",
                  "  let body = {};",
                  "  try { body = pm.response.json(); } catch (e) {}",
                  "  const pick = (path) => path.split('.').reduce((o, k) => (o == null ? o : o[k]), body);",
                  "  const sub_workspace_id = pick(\"id\");",
                  "  if (sub_workspace_id != null && sub_workspace_id !== '') pm.collectionVariables.set(\"sub_workspace_id\", String(sub_workspace_id));",
                  "}"
                ]
              }
            }
          ],
          "response": [
            {
              "name": "201 — created",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Created",
              "code": 201,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n  \"object\": \"workspace\",\n  \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  },\n  \"status\": \"active\",\n  \"created_at\": \"2026-11-02T09:14:07Z\",\n  \"updated_at\": \"2026-11-02T09:14:07Z\",\n  \"archived_at\": null\n}"
            },
            {
              "name": "409 — already exists",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_exists\",\n    \"message\": \"a sub-workspace with external_id \\\"68dbc1f4a2e9b7c3d5f01a26\\\" already exists under this account\"\n  },\n  \"workspace\": {\n    \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n    \"object\": \"workspace\",\n    \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n    \"name\": \"Solved Skin\",\n    \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n    \"kind\": \"shopify\",\n    \"timezone\": \"Asia/Kolkata\",\n    \"currency\": \"INR\",\n    \"profile\": {\n      \"supportContacts\": {\n        \"phoneNumber\": \"+919812345678\",\n        \"email\": \"care@solvedskin.in\"\n      },\n      \"trustSignals\": {\n        \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n        \"customersTillDate\": 120000,\n        \"storeRating\": 4.6\n      },\n      \"policyFramework\": {\n        \"returnPolicy\": {\n          \"windowDays\": 7,\n          \"refundTimelineDays\": 5\n        },\n        \"codPolicy\": {\n          \"enabled\": true,\n          \"additionalFee\": {\n            \"amount\": 49\n          }\n        }\n      }\n    },\n    \"status\": \"active\",\n    \"created_at\": \"2026-11-02T09:14:07Z\",\n    \"updated_at\": \"2026-11-02T09:14:07Z\",\n    \"archived_at\": null\n  }\n}"
            },
            {
              "name": "400 — sent with a Mirai-Workspace header",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Manage sub-workspaces from the account: drop the Mirai-Workspace header.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "List sub-workspaces",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/workspaces?status=active&limit=50",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspaces"
              ],
              "query": [
                {
                  "key": "status",
                  "value": "active",
                  "description": "active, archived or all"
                },
                {
                  "key": "external_id",
                  "value": "68dbc1f4a2e9b7c3d5f01a26",
                  "description": "only the brand with this external_id",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50"
                },
                {
                  "key": "cursor",
                  "value": "",
                  "description": "next_cursor from the previous page",
                  "disabled": true
                }
              ]
            },
            "description": "Your brands, newest first. `status` is `active` (the default), `archived` or `all`. `external_id` finds the one brand with that id, archived ones included when `status` is `all`.\n\n`limit` is 1 to 100. When `has_more` is true, pass `next_cursor` back as `cursor` for the next page."
          },
          "response": [
            {
              "name": "200 — one page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces?status=active&limit=50",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces"
                  ],
                  "query": [
                    {
                      "key": "status",
                      "value": "active",
                      "description": "active, archived or all"
                    },
                    {
                      "key": "external_id",
                      "value": "68dbc1f4a2e9b7c3d5f01a26",
                      "description": "only the brand with this external_id",
                      "disabled": true
                    },
                    {
                      "key": "limit",
                      "value": "50"
                    },
                    {
                      "key": "cursor",
                      "value": "",
                      "description": "next_cursor from the previous page",
                      "disabled": true
                    }
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n      \"object\": \"workspace\",\n      \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n      \"name\": \"Solved Skin\",\n      \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n      \"kind\": \"shopify\",\n      \"timezone\": \"Asia/Kolkata\",\n      \"currency\": \"INR\",\n      \"profile\": {\n        \"supportContacts\": {\n          \"phoneNumber\": \"+919812345678\",\n          \"email\": \"care@solvedskin.in\"\n        },\n        \"trustSignals\": {\n          \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n          \"customersTillDate\": 120000,\n          \"storeRating\": 4.6\n        },\n        \"policyFramework\": {\n          \"returnPolicy\": {\n            \"windowDays\": 7,\n            \"refundTimelineDays\": 5\n          },\n          \"codPolicy\": {\n            \"enabled\": true,\n            \"additionalFee\": {\n              \"amount\": 49\n            }\n          }\n        }\n      },\n      \"status\": \"active\",\n      \"created_at\": \"2026-11-02T09:14:07Z\",\n      \"updated_at\": \"2026-11-02T09:14:07Z\",\n      \"archived_at\": null\n    },\n    {\n      \"id\": \"ws_0b7e3d9a5c1f4e8b2a6d7c35\",\n      \"object\": \"workspace\",\n      \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n      \"name\": \"Acme Support Line\",\n      \"external_id\": null,\n      \"kind\": \"custom\",\n      \"timezone\": \"Asia/Kolkata\",\n      \"currency\": \"INR\",\n      \"profile\": {\n        \"supportContacts\": {\n          \"phoneNumber\": \"+919876543210\",\n          \"email\": \"support@acme.example\"\n        },\n        \"trustSignals\": {\n          \"valuePropositionOneLiner\": \"Premium 24x7 support for Acme customers.\"\n        }\n      },\n      \"status\": \"active\",\n      \"created_at\": \"2026-10-28T06:40:12Z\",\n      \"updated_at\": \"2026-10-28T06:40:12Z\",\n      \"archived_at\": null\n    }\n  ],\n  \"has_more\": false,\n  \"next_cursor\": null\n}"
            }
          ]
        },
        {
          "name": "Get a sub-workspace",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspaces",
                "{{sub_workspace_id}}"
              ]
            },
            "description": "One brand, by its `id` or its `external_id`. Archived brands can still be read."
          },
          "response": [
            {
              "name": "200 — the brand",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n  \"object\": \"workspace\",\n  \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  },\n  \"status\": \"active\",\n  \"created_at\": \"2026-11-02T09:14:07Z\",\n  \"updated_at\": \"2026-11-02T09:14:07Z\",\n  \"archived_at\": null\n}"
            },
            {
              "name": "404 — not one of yours",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_not_found\",\n    \"message\": \"No sub-workspace \\\"ws_6f1c0a9e2b7d4c3a8e5f9b10\\\" under this account.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Update a sub-workspace",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspaces",
                "{{sub_workspace_id}}"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Solved Skin India\",\n  \"timezone\": \"Asia/Kolkata\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Changes only the fields you send: `name`, `external_id`, `kind`, `timezone`, `currency` and `profile`. `profile` is replaced as a whole, so send all of it. `\"external_id\": null` removes the external id. The same uniqueness rules as creating apply, and a clash is `409 workspace_exists`."
          },
          "response": [
            {
              "name": "200 — updated",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Solved Skin India\",\n  \"timezone\": \"Asia/Kolkata\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n  \"object\": \"workspace\",\n  \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n  \"name\": \"Solved Skin India\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  },\n  \"status\": \"active\",\n  \"created_at\": \"2026-11-02T09:14:07Z\",\n  \"updated_at\": \"2026-11-05T13:21:09Z\",\n  \"archived_at\": null\n}"
            },
            {
              "name": "404 — not one of yours",
              "originalRequest": {
                "method": "PATCH",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Solved Skin India\",\n  \"timezone\": \"Asia/Kolkata\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_not_found\",\n    \"message\": \"No sub-workspace \\\"ws_6f1c0a9e2b7d4c3a8e5f9b10\\\" under this account.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Archive a sub-workspace",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}/archive",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspaces",
                "{{sub_workspace_id}}",
                "archive"
              ]
            },
            "description": "Stops the brand. From now on any request with its id or external id in the header gets `403 workspace_archived`. Its agents, calls and history are kept, and restoring brings them all back.\n\nA brand with a campaign that is still running can't be archived (`409 workspace_busy`). Pause or finish the campaign first."
          },
          "response": [
            {
              "name": "200 — archived",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}/archive",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}",
                    "archive"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n  \"object\": \"workspace\",\n  \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  },\n  \"status\": \"archived\",\n  \"created_at\": \"2026-11-02T09:14:07Z\",\n  \"updated_at\": \"2026-11-20T11:02:45Z\",\n  \"archived_at\": \"2026-11-20T11:02:45Z\"\n}"
            },
            {
              "name": "409 — a campaign is running",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}/archive",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}",
                    "archive"
                  ]
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_busy\",\n    \"message\": \"a campaign in this workspace is playing; pause or stop it before archiving the workspace\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Restore a sub-workspace",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}/restore",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspaces",
                "{{sub_workspace_id}}",
                "restore"
              ]
            },
            "description": "Makes an archived brand active again. Its name has to be free among your active brands, and your account has to be under its limit of active ones."
          },
          "response": [
            {
              "name": "200 — active again",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}/restore",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}",
                    "restore"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n  \"object\": \"workspace\",\n  \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n  \"name\": \"Solved Skin\",\n  \"external_id\": \"68dbc1f4a2e9b7c3d5f01a26\",\n  \"kind\": \"shopify\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"currency\": \"INR\",\n  \"profile\": {\n    \"supportContacts\": {\n      \"phoneNumber\": \"+919812345678\",\n      \"email\": \"care@solvedskin.in\"\n    },\n    \"trustSignals\": {\n      \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n      \"customersTillDate\": 120000,\n      \"storeRating\": 4.6\n    },\n    \"policyFramework\": {\n      \"returnPolicy\": {\n        \"windowDays\": 7,\n        \"refundTimelineDays\": 5\n      },\n      \"codPolicy\": {\n        \"enabled\": true,\n        \"additionalFee\": {\n          \"amount\": 49\n        }\n      }\n    }\n  },\n  \"status\": \"active\",\n  \"created_at\": \"2026-11-02T09:14:07Z\",\n  \"updated_at\": \"2026-11-21T08:30:00Z\",\n  \"archived_at\": null\n}"
            },
            {
              "name": "400 — sent with a Mirai-Workspace header",
              "originalRequest": {
                "method": "POST",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/workspaces/{{sub_workspace_id}}/restore",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspaces",
                    "{{sub_workspace_id}}",
                    "restore"
                  ]
                }
              },
              "status": "Bad Request",
              "code": 400,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"invalid_request\",\n    \"message\": \"Manage sub-workspaces from the account: drop the Mirai-Workspace header.\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Onboard a custom brand (v1)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/workspace/onboard/custom",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspace",
                "onboard",
                "custom"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Acme Support Line\",\n  \"currencyCode\": \"INR\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"supportContacts\": {\n    \"phoneNumber\": \"+919876543210\",\n    \"email\": \"support@acme.example\"\n  },\n  \"trustSignals\": {\n    \"valuePropositionOneLiner\": \"Premium 24x7 support for Acme customers.\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "v1's onboarding call, same path and same body, so a script written for v1 only needs a new base URL and key. It creates a sub-workspace of kind `custom`: `currencyCode` and `timezone` become its currency and timezone, and `supportContacts`, `trustSignals` and `policyFramework` go into its `profile`.\n\nThe answer keeps v1's `status`, `workspace` and `billing` fields and adds the new brand as `sub_workspace`. `workspace` is the id to send in the `Mirai-Workspace` header. `billing` is your account's wallet, which the brand spends from. For new integrations, *Create a sub-workspace* does the same with an `external_id`."
          },
          "response": [
            {
              "name": "200 — onboarded",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspace/onboard/custom",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspace",
                    "onboard",
                    "custom"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Acme Support Line\",\n  \"currencyCode\": \"INR\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"supportContacts\": {\n    \"phoneNumber\": \"+919876543210\",\n    \"email\": \"support@acme.example\"\n  },\n  \"trustSignals\": {\n    \"valuePropositionOneLiner\": \"Premium 24x7 support for Acme customers.\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"status\": \"active\",\n  \"workspace\": \"ws_0b7e3d9a5c1f4e8b2a6d7c35\",\n  \"billing\": {\n    \"type\": \"prepaid\",\n    \"creditBalance\": 18450.5,\n    \"negativeCreditAllowance\": 0\n  },\n  \"sub_workspace\": {\n    \"id\": \"ws_0b7e3d9a5c1f4e8b2a6d7c35\",\n    \"object\": \"workspace\",\n    \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n    \"name\": \"Acme Support Line\",\n    \"external_id\": null,\n    \"kind\": \"custom\",\n    \"timezone\": \"Asia/Kolkata\",\n    \"currency\": \"INR\",\n    \"profile\": {\n      \"supportContacts\": {\n        \"phoneNumber\": \"+919876543210\",\n        \"email\": \"support@acme.example\"\n      },\n      \"trustSignals\": {\n        \"valuePropositionOneLiner\": \"Premium 24x7 support for Acme customers.\"\n      }\n    },\n    \"status\": \"active\",\n    \"created_at\": \"2026-10-28T06:40:12Z\",\n    \"updated_at\": \"2026-10-28T06:40:12Z\",\n    \"archived_at\": null\n  }\n}"
            },
            {
              "name": "409 — the name is taken",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspace/onboard/custom",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspace",
                    "onboard",
                    "custom"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Acme Support Line\",\n  \"currencyCode\": \"INR\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"supportContacts\": {\n    \"phoneNumber\": \"+919876543210\",\n    \"email\": \"support@acme.example\"\n  },\n  \"trustSignals\": {\n    \"valuePropositionOneLiner\": \"Premium 24x7 support for Acme customers.\"\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Conflict",
              "code": 409,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_exists\",\n    \"message\": \"an active sub-workspace named \\\"Acme Support Line\\\" already exists under this account\"\n  },\n  \"workspace\": {\n    \"id\": \"ws_0b7e3d9a5c1f4e8b2a6d7c35\",\n    \"object\": \"workspace\",\n    \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n    \"name\": \"Acme Support Line\",\n    \"external_id\": null,\n    \"kind\": \"custom\",\n    \"timezone\": \"Asia/Kolkata\",\n    \"currency\": \"INR\",\n    \"profile\": {\n      \"supportContacts\": {\n        \"phoneNumber\": \"+919876543210\",\n        \"email\": \"support@acme.example\"\n      },\n      \"trustSignals\": {\n        \"valuePropositionOneLiner\": \"Premium 24x7 support for Acme customers.\"\n      }\n    },\n    \"status\": \"active\",\n    \"created_at\": \"2026-10-28T06:40:12Z\",\n    \"updated_at\": \"2026-10-28T06:40:12Z\",\n    \"archived_at\": null\n  }\n}"
            }
          ]
        },
        {
          "name": "Onboard a Shopify brand (v1)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/workspace/onboard/shopify",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "workspace",
                "onboard",
                "shopify"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Solved Skin\",\n  \"currencyCode\": \"INR\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"supportContacts\": {\n    \"phoneNumber\": \"+919812345678\",\n    \"email\": \"care@solvedskin.in\"\n  },\n  \"trustSignals\": {\n    \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n    \"customersTillDate\": 120000,\n    \"storeRating\": 4.6\n  },\n  \"policyFramework\": {\n    \"returnPolicy\": {\n      \"windowDays\": 7,\n      \"refundTimelineDays\": 5\n    },\n    \"codPolicy\": {\n      \"enabled\": true,\n      \"additionalFee\": {\n        \"amount\": 49\n      }\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "v1's Shopify onboarding, same path and same body. It creates a sub-workspace of kind `shopify` and needs no Shopify credentials: carts arrive with your calls, as before. The answer has the same shape as *Onboard a custom brand (v1)*."
          },
          "response": [
            {
              "name": "200 — onboarded",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/workspace/onboard/shopify",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "workspace",
                    "onboard",
                    "shopify"
                  ]
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"Solved Skin\",\n  \"currencyCode\": \"INR\",\n  \"timezone\": \"Asia/Kolkata\",\n  \"supportContacts\": {\n    \"phoneNumber\": \"+919812345678\",\n    \"email\": \"care@solvedskin.in\"\n  },\n  \"trustSignals\": {\n    \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n    \"customersTillDate\": 120000,\n    \"storeRating\": 4.6\n  },\n  \"policyFramework\": {\n    \"returnPolicy\": {\n      \"windowDays\": 7,\n      \"refundTimelineDays\": 5\n    },\n    \"codPolicy\": {\n      \"enabled\": true,\n      \"additionalFee\": {\n        \"amount\": 49\n      }\n    }\n  }\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"status\": \"active\",\n  \"workspace\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n  \"billing\": {\n    \"type\": \"prepaid\",\n    \"creditBalance\": 18450.5,\n    \"negativeCreditAllowance\": 0\n  },\n  \"sub_workspace\": {\n    \"id\": \"ws_6f1c0a9e2b7d4c3a8e5f9b10\",\n    \"object\": \"workspace\",\n    \"parent_id\": \"ws_2a9d4e7c1b3f5a8e6d0c4b21\",\n    \"name\": \"Solved Skin\",\n    \"external_id\": null,\n    \"kind\": \"shopify\",\n    \"timezone\": \"Asia/Kolkata\",\n    \"currency\": \"INR\",\n    \"profile\": {\n      \"supportContacts\": {\n        \"phoneNumber\": \"+919812345678\",\n        \"email\": \"care@solvedskin.in\"\n      },\n      \"trustSignals\": {\n        \"valuePropositionOneLiner\": \"Clean skincare, made in India\",\n        \"customersTillDate\": 120000,\n        \"storeRating\": 4.6\n      },\n      \"policyFramework\": {\n        \"returnPolicy\": {\n          \"windowDays\": 7,\n          \"refundTimelineDays\": 5\n        },\n        \"codPolicy\": {\n          \"enabled\": true,\n          \"additionalFee\": {\n            \"amount\": 49\n          }\n        }\n      }\n    },\n    \"status\": \"active\",\n    \"created_at\": \"2026-11-02T09:14:07Z\",\n    \"updated_at\": \"2026-11-02T09:14:07Z\",\n    \"archived_at\": null\n  }\n}"
            }
          ]
        },
        {
          "name": "Count one brand's calls",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Mirai-Workspace",
                "value": "{{sub_workspace_id}}",
                "description": "The brand's id or external_id."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v2/calls/summary",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "calls",
                "summary"
              ]
            },
            "description": "Any request acts as a brand with the `Mirai-Workspace` header. This one is *Count calls* for a single brand: its totals by channel and direction, which is the usage you'd bill that brand for. `GET /v2/calls` with the same header lists its calls."
          },
          "response": [
            {
              "name": "200 — one brand",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Mirai-Workspace",
                    "value": "{{sub_workspace_id}}",
                    "description": "The brand's id or external_id."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "summary"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"object\": \"call_summary\",\n  \"total\": 312,\n  \"by_channel\": {\n    \"phone\": 298,\n    \"web\": 14,\n    \"text\": 0,\n    \"realtime\": 0\n  },\n  \"by_direction\": {\n    \"outbound\": 301,\n    \"inbound\": 11\n  },\n  \"duration_secs\": 21877,\n  \"from\": null,\n  \"to\": null\n}"
            },
            {
              "name": "404 — not one of your brands",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Mirai-Workspace",
                    "value": "{{sub_workspace_id}}",
                    "description": "The brand's id or external_id."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "summary"
                  ]
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_not_found\",\n    \"message\": \"No sub-workspace \\\"ws_6f1c0a9e2b7d4c3a8e5f9b10\\\" under this account.\"\n  }\n}"
            },
            {
              "name": "403 — an archived brand",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "Mirai-Workspace",
                    "value": "{{sub_workspace_id}}",
                    "description": "The brand's id or external_id."
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v2/calls/summary",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "calls",
                    "summary"
                  ]
                }
              },
              "status": "Forbidden",
              "code": 403,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"workspace_archived\",\n    \"message\": \"Sub-workspace \\\"ws_6f1c0a9e2b7d4c3a8e5f9b10\\\" is archived. Restore it with POST /v2/workspaces/ws_6f1c0a9e2b7d4c3a8e5f9b10/restore to use it again.\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Reference",
      "description": "The voice catalogue, and the API contract as a machine-readable document.",
      "item": [
        {
          "name": "List voices",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/voices",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "voices"
              ]
            },
            "description": "Every voice your key can use. Any `voice_id` listed here is valid in an agent's `voice.voice_id`."
          },
          "response": [
            {
              "name": "200 — the catalogue",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/voices",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "voices"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"data\": [\n    {\n      \"voice_id\": \"ashu\",\n      \"name\": \"आशु\",\n      \"language\": \"hi\"\n    },\n    {\n      \"voice_id\": \"neha\",\n      \"name\": \"नेहा\",\n      \"language\": \"hi\"\n    },\n    {\n      \"voice_id\": \"shruti\",\n      \"name\": \"श्रुति\",\n      \"language\": \"hi\"\n    },\n    {\n      \"voice_id\": \"sameer\",\n      \"name\": \"समीर\",\n      \"language\": \"hi\"\n    }\n  ]\n}"
            }
          ]
        },
        {
          "name": "Get the API contract",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v2/schema",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v2",
                "schema"
              ]
            },
            "description": "The whole API as an OpenAPI 3.1 document: every operation, its parameters and its request body schema. Handy for generating a client or checking a body before you send it. It needs no key."
          },
          "response": [
            {
              "name": "200 — OpenAPI document (trimmed)",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v2/schema",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v2",
                    "schema"
                  ]
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": {\n    \"title\": \"Mirai product API\",\n    \"version\": \"2026-10-07.secondary-languages\"\n  },\n  \"paths\": {\n    \"/v2/calls\": {\n      \"post\": {\n        \"operationId\": \"create_call\",\n        \"summary\": \"Place a real call or create a web or realtime session. …\"\n      }\n    }\n  },\n  \"components\": {\n    \"schemas\": {\n      \"Agent\": {\n        \"type\": \"object\"\n      },\n      \"Call\": {\n        \"type\": \"object\"\n      }\n    }\n  }\n}"
            }
          ]
        }
      ]
    }
  ],
  "variable": [
    {
      "key": "base_url",
      "value": "https://sandbox.voice.miraiminds.co",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "sk_live_REPLACE_ME",
      "type": "string"
    },
    {
      "key": "test_number",
      "value": "+91XXXXXXXXXX",
      "type": "string"
    },
    {
      "key": "agent_id",
      "value": "agt_01K2M4P7QRSTVWXYZ0A1B2C3",
      "type": "string"
    },
    {
      "key": "agent_revision",
      "value": "1",
      "type": "string"
    },
    {
      "key": "revision",
      "value": "1",
      "type": "string"
    },
    {
      "key": "call_id",
      "value": "call_01K2M4RB8CDEFGHJKMNPQRST",
      "type": "string"
    },
    {
      "key": "control_id",
      "value": "ctl_01K2M5X8C2E4G6J8M0P2R4T6V8",
      "type": "string"
    },
    {
      "key": "refine_id",
      "value": "frf_01KZR3Q5S89NTXQ40V3KYN4JMA",
      "type": "string"
    },
    {
      "key": "tool_name",
      "value": "book_slot",
      "type": "string"
    },
    {
      "key": "secret_name",
      "value": "crm_key",
      "type": "string"
    },
    {
      "key": "callback_id",
      "value": "cbk_5f2a9c0e71d34b8a6e19c047",
      "type": "string"
    },
    {
      "key": "webhook_endpoint_id",
      "value": "whe_01K9V2C4E6G8J0M2P4R6T8W0Y2",
      "type": "string"
    },
    {
      "key": "webhook_subscription_id",
      "value": "whs_01K9V2D5F7H9K1N3Q5S7V9X1Z3",
      "type": "string"
    },
    {
      "key": "webhook_event_id",
      "value": "evt_01K9V2E6G8J0M2P4R6T8W0Y2A4",
      "type": "string"
    },
    {
      "key": "webhook_delivery_id",
      "value": "whd_01K9V2F7H9K1N3Q5S7V9X1Z3B5",
      "type": "string"
    },
    {
      "key": "campaign_id",
      "value": "cmp_01K79Q4T6W8XZ2B5D7F9H3JKMN",
      "type": "string"
    },
    {
      "key": "contact_id",
      "value": "lead-1042",
      "type": "string"
    },
    {
      "key": "dnc_phone",
      "value": "%2B919812345678",
      "type": "string"
    },
    {
      "key": "phone_number_id",
      "value": "phn_01K9Q3A7C2E4G6J8M0P2R4T6V8",
      "type": "string"
    },
    {
      "key": "pool_id",
      "value": "ppl_01K9V2C4E6G8J0M2P4R6T8W0Y2",
      "type": "string"
    },
    {
      "key": "requirement_id",
      "value": "9a3c5e71-2b4d-4f86-a1c9-7e0d2f4b6a83",
      "type": "string"
    },
    {
      "key": "onboarding_id",
      "value": "tbo_01K9N4R7T0W3Y6B9D2G5J8M1P4",
      "type": "string"
    },
    {
      "key": "compliance_id",
      "value": "4f1a9c2e-7b3d-4e8a-9c61-2d5f8b0e3a17",
      "type": "string"
    },
    {
      "key": "city",
      "value": "mumbai",
      "type": "string"
    },
    {
      "key": "available_number",
      "value": "+912248901234",
      "type": "string"
    },
    {
      "key": "rental_id",
      "value": "rent_01K9Q4B8D3F5H7K9N1Q3S5W7Y9",
      "type": "string"
    },
    {
      "key": "connection_id",
      "value": "tcn_01K9Q2W5D8F3H6J9KMNPQRSTVW",
      "type": "string"
    },
    {
      "key": "sip_connection_id",
      "value": "tcn_01K9S3X6E9G4J7K0MPQRSTVWXY",
      "type": "string"
    },
    {
      "key": "plivo_number",
      "value": "+918048123456",
      "type": "string"
    },
    {
      "key": "verification_id",
      "value": "verify_01K9Q5C9E4G6J8M1P3R5T7X9Z1",
      "type": "string"
    },
    {
      "key": "transcription_id",
      "value": "trn_01M3XRSFXW77RHEQ85979AJXAF",
      "type": "string"
    },
    {
      "key": "stt_request_id",
      "value": "stt_01K7C2M3Q4R7T9V2X5Y8A1B4C7-1",
      "type": "string"
    },
    {
      "key": "sub_workspace_id",
      "value": "ws_6f1c0a9e2b7d4c3a8e5f9b10",
      "type": "string"
    }
  ]
}
