{
  "openapi": "3.1.0",
  "info": {
    "title": "API Wevichat",
    "version": "1.0.0",
    "summary": "Contatos, conversas, mensagens, webhooks e agentes de IA da Wevichat.",
    "description": "API REST da Wevichat. Tudo é JSON sobre HTTPS, autenticado por uma chave\n`wevi_` no header `Authorization`.\n\nCada chave carrega escopos e pode ter validade. Ler funciona em qualquer\nplano; escrever e enviar mensagem exige um plano com o recurso de API.\n\nGuias, exemplos e a explicação de cada conceito estão em\nhttps://wevi.chat/docs/api.\n",
    "contact": {
      "name": "Suporte Wevichat",
      "url": "https://wevi.chat/ajuda",
      "email": "contato@wevi.chat"
    },
    "license": {
      "name": "Proprietária"
    }
  },
  "servers": [
    {
      "url": "https://api.wevi.chat/functions/v1",
      "description": "Produção"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Contatos",
      "description": "Quem fala com você. Cada contato guarda telefone, email, etiquetas,\ncampos próprios, dono da carteira e a etapa em cada funil.\n\nO telefone é a chave: mande sempre no formato internacional\n(`+5548988060000`). A gravação normaliza o que chegar, e a busca aceita\nos formatos antigos, mas o padrão evita contato duplicado.\n\nUse `updated_since` para sincronizar só o que mudou desde a última vez,\nem vez de varrer a base inteira.\n"
    },
    {
      "name": "Conversas",
      "description": "O histórico de cada atendimento e o controle de quem responde.\n\nA IA responde sozinha até alguém assumir. Ao assumir, ela para de\nresponder naquela conversa até você devolver. É por aqui que um sistema\nexterno entra no meio de um atendimento em andamento.\n\nLembre da janela de 24 horas do WhatsApp: passado esse prazo desde a\núltima mensagem do cliente, só template aprovado sai.\n"
    },
    {
      "name": "Mensagens",
      "description": "O envio pelo WhatsApp, todo por `POST /messages`.\n\nUm endpoint só resolve todos os tipos: texto, template aprovado, botões,\nlista, link com botão, pedido de localização e cards do catálogo. O tipo\nvai no corpo.\n\nMande sempre uma `idempotency_key`. Se a requisição repetir por queda de\nrede ou nova tentativa, a mensagem não sai duas vezes.\n\nOs endpoints antigos `/send-*` continuam funcionando e não vão sair sem\naviso, mas o que recebe recurso novo é este.\n"
    },
    {
      "name": "Agentes",
      "description": "Converse com os seus agentes de IA direto pela API, sem passar pelo\nWhatsApp. Serve para colocar o agente num app próprio, num site interno\nou num teste automatizado.\n\nA conversa mantém contexto: guarde o identificador devolvido na primeira\nchamada e mande nas seguintes.\n\nO agente usa a chave de IA da sua organização, então o consumo aparece\nnormalmente no seu painel.\n"
    },
    {
      "name": "Campanhas",
      "description": "Disparo para uma lista de contatos e o acompanhamento do resultado.\n\nCrie a campanha, acompanhe o andamento e leia o resultado por contato.\nRespeita quem pediu para sair da lista.\n\nExige plano Pro ou Ultra.\n"
    },
    {
      "name": "Automações",
      "description": "Comece um fluxo de automação quando algo acontece no seu sistema.\n\nO caso comum é o seu CRM avisar que o negócio mudou de estágio e a\nWevichat cuidar da conversa a partir dali. O contato é criado ou\natualizado na mesma chamada, então você não precisa cadastrar antes.\n"
    },
    {
      "name": "Webhooks",
      "description": "O caminho inverso: em vez de você perguntar, a Wevichat avisa.\n\nRegistre um endereço, escolha entre os 30 eventos e receba a notificação\nassim que a coisa acontecer. Cada entrega vai assinada no cabeçalho\n`Wevi-Signature`, e o segredo aparece uma vez só, na criação.\n\nConfira essa assinatura sempre. Sem ela, quem descobrir o seu endereço\nconsegue forjar um evento. Se o seu servidor falhar, a entrega é\nrepetida com intervalos crescentes, então o mesmo evento pode chegar\nduas vezes: trate pelo identificador do evento.\n"
    },
    {
      "name": "Configuração",
      "description": "O que sustenta o resto: números de WhatsApp conectados, templates\naprovados pela Meta e os metadados da sua organização.\n\nConsulte os metadados para descobrir, sem chutar, quais etiquetas,\ncampos próprios, funis e atendentes existem antes de gravar um contato.\n"
    },
    {
      "name": "Parceiros",
      "description": "A API do programa Whitelabel. O parceiro cria o espaço do cliente dentro\ndo próprio produto, gera a chave daquele espaço e lê o consumo, sem\npassar pelo painel.\n\nExige o escopo `partner:manage` e que a organização da chave seja\nparceira. Fale com a gente se quiser entrar no programa.\n"
    },
    {
      "name": "Sistema",
      "description": "Dados da organização, consumo do mês, relatórios e disponibilidade.\n\n`GET /health` responde sem autenticação, então serve para apontar o seu\nmonitoramento. Os outros dizem em que plano você está, quanto já usou e\nquanto falta para o limite.\n"
    }
  ],
  "paths": {
    "/contacts": {
      "get": {
        "tags": [
          "Contatos"
        ],
        "summary": "Lista ou busca contatos",
        "description": "Sem identificador na query, devolve a lista paginada da organização. Com\n`id`, `email`, `phone` ou `cpf`, devolve um contato só, ou `404` quando\nnão existe.\n\nPara sincronizar com o seu sistema, use `updated_since` com a data da\núltima sincronização em vez de varrer a base inteira toda vez.\n",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Busca o contato por identificador interno."
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca por email exato."
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca por telefone. Aceita qualquer formato, inclusive os antigos sem o código do país."
          },
          {
            "name": "cpf",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca pelo CPF gravado como identificador do contato."
          },
          {
            "name": "q",
            "in": "query",
            "description": "Busca por nome, email ou telefone",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "description": "Etiqueta por nome ou id",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pipeline",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por funil, pelo nome ou pelo id."
          },
          {
            "name": "stage",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por etapa dentro do funil informado em `pipeline`."
          },
          {
            "name": "lost",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "`true` traz só quem foi marcado como perdido no funil."
          },
          {
            "name": "assigned_to",
            "in": "query",
            "description": "UUID do dono, ou `none`",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "opted_out",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "`true` traz só quem pediu para não receber mais."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de contatos, ou um contato quando veio identificador",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-1111-4111-8111-111111111111",
                      "name": "Marina Alves",
                      "email": "marina.alves@exemplo.com.br",
                      "phone": "5511987654321",
                      "notes": null,
                      "custom_fields": {
                        "plano": "Premium",
                        "ultima_consulta": "2026-08-14"
                      },
                      "tags": [
                        {
                          "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                          "name": "Lead quente",
                          "color": "#22D650"
                        }
                      ],
                      "pipelines": [
                        {
                          "pipeline_id": "c0a80101-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
                          "pipeline_name": "Funil de vendas",
                          "stage_id": "c0a80101-cccc-4ccc-8ccc-cccccccccccc",
                          "stage_name": "Proposta enviada",
                          "entered_stage_at": "2026-09-01T14:22:00Z",
                          "lost_at": null,
                          "lost_reason": null
                        }
                      ],
                      "assigned_user": {
                        "id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd",
                        "name": "Paula Ribeiro",
                        "email": "paula@clinicabemestar.com.br",
                        "role": "atendente"
                      },
                      "identifiers": [
                        {
                          "type": "phone",
                          "value": "5511987654321",
                          "label": null
                        },
                        {
                          "type": "email",
                          "value": "marina.alves@exemplo.com.br",
                          "label": null
                        }
                      ],
                      "stats": {
                        "conversation_count": 3,
                        "first_seen_at": "2026-06-02T10:00:00Z",
                        "last_seen_at": "2026-09-05T18:41:00Z",
                        "channels": [
                          "whatsapp"
                        ]
                      },
                      "opted_out_at": null,
                      "assigned_at": "2026-09-01T14:22:00Z",
                      "assignment_source": "manual",
                      "created_at": "2026-06-02T10:00:00Z",
                      "updated_at": "2026-09-05T18:41:00Z"
                    }
                  ],
                  "next_cursor": "eyJ1IjoiMjAyNi0wOS0wNVQxODo0MTowMFoifQ",
                  "has_more": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Cria ou atualiza um contato",
        "description": "Identifica o contato por email ou telefone. Existindo, atualiza os campos\nque vieram; senão, cria. Os campos que você não mandar ficam como estão.\n\nAs chaves de `fields` precisam existir em Campos personalizados. Consulte\n`GET /contacts-schema` antes se não souber quais são, em vez de chutar.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpsert"
              },
              "example": {
                "phone": "+55 11 98765-4321",
                "name": "Marina Alves",
                "email": "marina.alves@exemplo.com.br",
                "tags": [
                  "Lead quente"
                ],
                "fields": {
                  "plano": "Premium"
                },
                "assigned_user_email": "paula@clinicabemestar.com.br"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contato criado ou atualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactUpsertResult"
                },
                "example": {
                  "id": "c0a80101-1111-4111-8111-111111111111",
                  "name": "Marina Alves",
                  "email": "marina.alves@exemplo.com.br",
                  "phone": "5511987654321",
                  "custom_fields": {
                    "plano": "Premium"
                  },
                  "tags": [
                    {
                      "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                      "name": "Lead quente",
                      "color": "#22D650"
                    }
                  ],
                  "opted_out_at": null,
                  "created_at": "2026-06-02T10:00:00Z",
                  "updated_at": "2026-09-08T12:00:00Z",
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "tags_assigned": [
                    {
                      "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                      "name": "Lead quente",
                      "created": false
                    }
                  ],
                  "assigned_user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+55 11 98765-4321\",\n    \"name\": \"Marina Alves\",\n    \"email\": \"marina.alves@exemplo.com.br\",\n    \"tags\": [\n      \"Lead quente\"\n    ],\n    \"fields\": {\n      \"plano\": \"Premium\"\n    },\n    \"assigned_user_email\": \"paula@clinicabemestar.com.br\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+55 11 98765-4321\",\n    \"name\": \"Marina Alves\",\n    \"email\": \"marina.alves@exemplo.com.br\",\n    \"tags\": [\n      \"Lead quente\"\n    ],\n    \"fields\": {\n      \"plano\": \"Premium\"\n    },\n    \"assigned_user_email\": \"paula@clinicabemestar.com.br\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+55 11 98765-4321\",\n        \"name\": \"Marina Alves\",\n        \"email\": \"marina.alves@exemplo.com.br\",\n        \"tags\": [\n            \"Lead quente\"\n        ],\n        \"fields\": {\n            \"plano\": \"Premium\"\n        },\n        \"assigned_user_email\": \"paula@clinicabemestar.com.br\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+55 11 98765-4321\",\"name\":\"Marina Alves\",\"email\":\"marina.alves@exemplo.com.br\",\"tags\":[\"Lead quente\"],\"fields\":{\"plano\":\"Premium\"},\"assigned_user_email\":\"paula@clinicabemestar.com.br\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/batch": {
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Cria ou atualiza até 100 contatos",
        "description": "Até 100 contatos por chamada, com a mesma regra do `POST /contacts` item a\nitem. Um item ruim não derruba os outros: a resposta traz o resultado de\ncada um, na ordem em que vieram.\n\nServe para a carga inicial a partir do seu sistema. Para o dia a dia,\nprefira uma chamada por contato quando ele mudar.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contacts"
                ],
                "properties": {
                  "contacts": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "$ref": "#/components/schemas/ContactUpsertItem"
                    }
                  }
                }
              },
              "example": {
                "contacts": [
                  {
                    "phone": "+5511987654321",
                    "name": "Marina Alves",
                    "tags": [
                      "Lead quente"
                    ]
                  },
                  {
                    "email": "joao@exemplo.com.br",
                    "name": "João Prado"
                  },
                  {
                    "name": "Sem identificador"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado item a item",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                },
                "example": {
                  "processed": 3,
                  "succeeded": 2,
                  "failed": 1,
                  "results": [
                    {
                      "index": 0,
                      "ok": true,
                      "contact_id": "c0a80101-1111-4111-8111-111111111111",
                      "tags_assigned": []
                    },
                    {
                      "index": 1,
                      "ok": true,
                      "contact_id": "c0a80101-1112-4111-8111-111111111112",
                      "tags_assigned": []
                    },
                    {
                      "index": 2,
                      "ok": false,
                      "error": "missing_identifier",
                      "message": "Informe email ou phone."
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/batch\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"contacts\": [\n      {\n        \"phone\": \"+5511987654321\",\n        \"name\": \"Marina Alves\",\n        \"tags\": [\n          \"Lead quente\"\n        ]\n      },\n      {\n        \"email\": \"joao@exemplo.com.br\",\n        \"name\": \"João Prado\"\n      },\n      {\n        \"name\": \"Sem identificador\"\n      }\n    ]\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/batch\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"contacts\": [\n      {\n        \"phone\": \"+5511987654321\",\n        \"name\": \"Marina Alves\",\n        \"tags\": [\n          \"Lead quente\"\n        ]\n      },\n      {\n        \"email\": \"joao@exemplo.com.br\",\n        \"name\": \"João Prado\"\n      },\n      {\n        \"name\": \"Sem identificador\"\n      }\n    ]\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/batch\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"contacts\": [\n            {\n                \"phone\": \"+5511987654321\",\n                \"name\": \"Marina Alves\",\n                \"tags\": [\n                    \"Lead quente\"\n                ]\n            },\n            {\n                \"email\": \"joao@exemplo.com.br\",\n                \"name\": \"João Prado\"\n            },\n            {\n                \"name\": \"Sem identificador\"\n            }\n        ]\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/batch\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"contacts\":[{\"phone\":\"+5511987654321\",\"name\":\"Marina Alves\",\"tags\":[\"Lead quente\"]},{\"email\":\"joao@exemplo.com.br\",\"name\":\"João Prado\"},{\"name\":\"Sem identificador\"}]}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Contatos"
        ],
        "summary": "Um contato",
        "responses": {
          "200": {
            "description": "Contato",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "c0a80101-1111-4111-8111-111111111111",
                  "name": "Marina Alves",
                  "email": "marina.alves@exemplo.com.br",
                  "phone": "5511987654321",
                  "notes": "Prefere ser chamada de manhã.",
                  "custom_fields": {
                    "plano": "Premium"
                  },
                  "tags": [
                    {
                      "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                      "name": "Lead quente",
                      "color": "#22D650"
                    }
                  ],
                  "pipelines": [],
                  "assigned_user": null,
                  "identifiers": [
                    {
                      "type": "phone",
                      "value": "5511987654321",
                      "label": null
                    }
                  ],
                  "stats": {
                    "conversation_count": 3,
                    "first_seen_at": "2026-06-02T10:00:00Z",
                    "last_seen_at": "2026-09-05T18:41:00Z",
                    "channels": [
                      "whatsapp"
                    ]
                  },
                  "opted_out_at": null,
                  "created_at": "2026-06-02T10:00:00Z",
                  "updated_at": "2026-09-05T18:41:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um contato, com etiquetas, campos personalizados, posição nos funis, dono da carteira e as estatísticas do relacionamento.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "patch": {
        "tags": [
          "Contatos"
        ],
        "summary": "Altera um contato",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "fields": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "replace_fields": {
                    "type": "boolean",
                    "description": "Com true, `fields` substitui tudo em vez de mesclar."
                  }
                }
              },
              "example": {
                "name": "Marina Alves Souza",
                "fields": {
                  "plano": "Ultra"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contato atualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "c0a80101-1111-4111-8111-111111111111",
                  "name": "Marina Alves Souza",
                  "email": "marina.alves@exemplo.com.br",
                  "phone": "5511987654321",
                  "custom_fields": {
                    "plano": "Ultra"
                  },
                  "tags": [],
                  "updated_at": "2026-09-08T12:05:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Altera só os campos que vieram no corpo. Por padrão, `fields` é mesclado\ncom o que já existe; mande `replace_fields: true` para trocar o conjunto\ninteiro.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X PATCH \"https://api.wevi.chat/functions/v1/contacts/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Marina Alves Souza\",\n    \"fields\": {\n      \"plano\": \"Ultra\"\n    }\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}\", {\n  method: \"PATCH\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Marina Alves Souza\",\n    \"fields\": {\n      \"plano\": \"Ultra\"\n    }\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.patch(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"name\": \"Marina Alves Souza\",\n        \"fields\": {\n            \"plano\": \"Ultra\"\n        }\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"PATCH\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"name\":\"Marina Alves Souza\",\"fields\":{\"plano\":\"Ultra\"}}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Contatos"
        ],
        "summary": "Anonimiza ou apaga um contato",
        "description": "Por padrão anonimiza: apaga nome, telefone, email e campos personalizados,\ne mantém as conversas sem identificação, para os números do período\ncontinuarem batendo. Com `?mode=erase`, apaga o contato e tudo que aponta\npara ele, sem volta.\n\nAnonimizar costuma ser o certo para um pedido de exclusão de dados: atende\no pedido sem falsear o histórico do atendimento.\n",
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "anonymize",
                "erase"
              ],
              "default": "anonymize"
            },
            "description": "`anonymize` (padrão) preserva o histórico sem identificação. `erase` apaga tudo."
          }
        ],
        "responses": {
          "200": {
            "description": "Contato anonimizado ou apagado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "mode": "anonymize"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/contacts/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/conversations": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Contatos"
        ],
        "summary": "Conversas do contato",
        "responses": {
          "200": {
            "description": "Lista de conversas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-2222-4222-8222-222222222222",
                      "status": "open",
                      "channel": "whatsapp",
                      "connection_id": "c0a80101-4444-4444-8444-444444444444",
                      "user": {
                        "name": "Marina Alves",
                        "email": null,
                        "phone": "5511987654321",
                        "metadata": null
                      },
                      "tags": [],
                      "awaiting_reply": true,
                      "created_at": "2026-09-05T18:30:00Z",
                      "last_message_at": "2026-09-05T18:41:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As conversas deste contato, da mais recente para a mais antiga.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts/{id}/conversations\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/conversations\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/conversations\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/conversations\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/history": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Contatos"
        ],
        "summary": "Etapas, trocas de dono e notas, em ordem",
        "responses": {
          "200": {
            "description": "Linha do tempo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactHistoryList"
                },
                "example": {
                  "data": [
                    {
                      "type": "stage_changed",
                      "at": "2026-09-01T14:22:00Z",
                      "detail": {
                        "pipeline": "Funil de vendas",
                        "from": "Contato",
                        "to": "Proposta enviada",
                        "source": "api"
                      }
                    },
                    {
                      "type": "assigned",
                      "at": "2026-09-01T14:22:00Z",
                      "detail": {
                        "user": "Paula Ribeiro"
                      }
                    },
                    {
                      "type": "note",
                      "at": "2026-08-20T09:10:00Z",
                      "detail": {
                        "body": "Pediu retorno depois do dia 10."
                      }
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Mudanças de etapa, trocas de dono e notas, em ordem cronológica. É o que\nresponde \"por que este contato está nesta etapa\" sem abrir o painel.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts/{id}/history\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/history\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/history\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/history\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/export": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Contatos"
        ],
        "summary": "Exporta os dados do contato",
        "description": "Tudo que temos sobre a pessoa num JSON só: cadastro, identificadores,\netiquetas, posição nos funis, notas, conversas e mensagens. É o que\nentregar quando alguém exercer o direito de portabilidade.\n",
        "responses": {
          "200": {
            "description": "Exportação completa",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                },
                "example": {
                  "contact": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "conversations": [
                    {
                      "id": "c0a80101-2222-4222-8222-222222222222",
                      "channel": "whatsapp",
                      "created_at": "2026-09-05T18:30:00Z"
                    }
                  ],
                  "messages": [
                    {
                      "id": "c0a80101-9999-4999-8999-999999999991",
                      "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                      "role": "user",
                      "content": "Bom dia, gostaria de agendar.",
                      "created_at": "2026-09-05T18:30:00Z"
                    }
                  ],
                  "notes": [],
                  "exported_at": "2026-09-08T12:10:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts/{id}/export\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/export\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/export\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/export\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/notes": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Contatos"
        ],
        "summary": "Notas do contato",
        "responses": {
          "200": {
            "description": "Lista de notas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactNoteList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-eeee-4eee-8eee-eeeeeeeeeeee",
                      "body": "Pediu retorno depois do dia 10.",
                      "created_at": "2026-08-20T09:10:00Z",
                      "created_by": null
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As notas internas do contato, da mais recente para a mais antiga. O cliente nunca vê isto.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts/{id}/notes\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/notes\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/notes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/notes\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Adiciona uma nota",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "body"
                ],
                "properties": {
                  "body": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "body": "Cliente pediu orçamento de clareamento."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Nota criada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactNote"
                },
                "example": {
                  "id": "c0a80101-eeee-4eee-8eee-eeeeeeeeeeef",
                  "body": "Cliente pediu orçamento de clareamento.",
                  "created_at": "2026-09-08T12:12:00Z",
                  "created_by": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Adiciona uma nota ao contato, sem apagar as anteriores.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/{id}/notes\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"body\": \"Cliente pediu orçamento de clareamento.\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/notes\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"body\": \"Cliente pediu orçamento de clareamento.\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/notes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"body\": \"Cliente pediu orçamento de clareamento.\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/notes\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"body\":\"Cliente pediu orçamento de clareamento.\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/merge": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Funde outro contato neste",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contact_id"
                ],
                "properties": {
                  "contact_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              },
              "example": {
                "contact_id": "c0a80101-1112-4111-8111-111111111112"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contatos fundidos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "c0a80101-1111-4111-8111-111111111111",
                  "name": "Marina Alves",
                  "phone": "5511987654321",
                  "identifiers": [
                    {
                      "type": "phone",
                      "value": "5511987654321",
                      "label": null
                    },
                    {
                      "type": "email",
                      "value": "marina@exemplo.com.br",
                      "label": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Funde o contato informado em `contact_id` neste, que sobrevive. Conversas,\nmensagens, etiquetas, notas e identificadores passam para cá; o outro\ndeixa de existir.\n\nUse quando a mesma pessoa entrou duas vezes, por exemplo pelo site e\ndepois pelo WhatsApp com outro número.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/{id}/merge\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"contact_id\": \"c0a80101-1112-4111-8111-111111111112\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/merge\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"contact_id\": \"c0a80101-1112-4111-8111-111111111112\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/merge\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"contact_id\": \"c0a80101-1112-4111-8111-111111111112\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/merge\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"contact_id\":\"c0a80101-1112-4111-8111-111111111112\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/opt-out": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Marca que o contato não quer mais receber",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Corpo opcional; hoje nenhum campo é usado."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Feito",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "c0a80101-1111-4111-8111-111111111111",
                  "name": "Marina Alves",
                  "opted_out_at": "2026-09-08T12:15:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Marca que o contato não quer mais receber. A partir daí, campanha,\nautomação e disparo avulso não saem para ele. Resposta dentro da janela de\n24 horas continua funcionando, porque aí é conversa que ele mesmo começou.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/{id}/opt-out\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/opt-out\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({}),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/opt-out\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/opt-out\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/{id}/opt-in": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Volta a permitir envio para o contato",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Corpo opcional; hoje nenhum campo é usado."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Feito",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "c0a80101-1111-4111-8111-111111111111",
                  "name": "Marina Alves",
                  "opted_out_at": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Desfaz o opt-out. Use só quando a pessoa pedir de volta, e guarde no seu lado a prova de que pediu.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/{id}/opt-in\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/{id}/opt-in\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({}),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/{id}/opt-in\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/{id}/opt-in\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/tag": {
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Aplica uma etiqueta",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "tag": {
                    "type": "string"
                  },
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "tag": "Lead quente"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Etiqueta aplicada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "tag": {
                    "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                    "name": "Lead quente",
                    "created": false
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Aplica uma etiqueta ao contato, criando a etiqueta se ela ainda não\nexistir. Identifique o contato por `id`, `email`, `phone` ou `cpf` no\ncorpo.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/tag\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"tag\": \"Lead quente\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/tag\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"tag\": \"Lead quente\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/tag\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"tag\": \"Lead quente\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/tag\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"tag\":\"Lead quente\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Contatos"
        ],
        "summary": "Remove uma etiqueta",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "tag": {
                    "type": "string"
                  },
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "tag": "Lead quente"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Etiqueta removida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Tira uma etiqueta do contato. A etiqueta continua existindo na organização.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/contacts/tag\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"tag\": \"Lead quente\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/tag\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"tag\": \"Lead quente\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/contacts/tag\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"tag\": \"Lead quente\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/tag\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"tag\":\"Lead quente\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/stage": {
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Move o contato no funil",
        "description": "Move o contato de etapa no funil, ou marca como perdido. Sem `pipeline`,\nusa o funil padrão da organização. Aceita nome ou id tanto para o funil\nquanto para a etapa.\n\nMarcar como perdido tira o contato do fluxo do funil sem apagar o\nhistórico: \"`lost: true` com um `reason` que ajude a entender depois.\"\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "pipeline": {
                    "type": "string"
                  },
                  "stage": {
                    "type": "string"
                  },
                  "lost": {
                    "type": "boolean"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "pipeline": "Funil de vendas",
                "stage": "Proposta enviada"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Etapa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "pipeline": {
                    "id": "c0a80101-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
                    "name": "Funil de vendas"
                  },
                  "stage": {
                    "id": "c0a80101-cccc-4ccc-8ccc-cccccccccccc",
                    "name": "Proposta enviada"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/stage\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"pipeline\": \"Funil de vendas\",\n    \"stage\": \"Proposta enviada\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/stage\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"pipeline\": \"Funil de vendas\",\n    \"stage\": \"Proposta enviada\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/stage\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"pipeline\": \"Funil de vendas\",\n        \"stage\": \"Proposta enviada\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/stage\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"pipeline\":\"Funil de vendas\",\"stage\":\"Proposta enviada\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/assign": {
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Define o dono da carteira",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "assigned_user_email"
                ],
                "properties": {
                  "assigned_user_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "assigned_user_email": "paula@clinicabemestar.com.br"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dono definido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "assigned_user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Define o dono da carteira pelo email de um membro da organização. O email\nprecisa ser de alguém que já faz parte da equipe.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/assign\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"assigned_user_email\": \"paula@clinicabemestar.com.br\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/assign\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"assigned_user_email\": \"paula@clinicabemestar.com.br\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/assign\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"assigned_user_email\": \"paula@clinicabemestar.com.br\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/assign\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"assigned_user_email\":\"paula@clinicabemestar.com.br\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Contatos"
        ],
        "summary": "Remove o dono da carteira",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dono removido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Deixa o contato sem dono. Ele volta para a fila geral.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/contacts/assign\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/assign\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/contacts/assign\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/assign\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/note": {
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Grava as notas do cadastro do contato",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "note"
                ],
                "properties": {
                  "note": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "note": "Prefere ser chamada de manhã."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Notas gravadas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Grava o campo de anotação do cadastro, substituindo o que estava lá.\nMande `null` ou string vazia para limpar.\n\nDiferente de `POST /contacts/{id}/notes`, que acrescenta uma nota nova ao\nhistórico sem apagar as anteriores.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/note\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"note\": \"Prefere ser chamada de manhã.\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/note\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"note\": \"Prefere ser chamada de manhã.\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/note\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"note\": \"Prefere ser chamada de manhã.\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/note\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"note\":\"Prefere ser chamada de manhã.\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts/field": {
      "post": {
        "tags": [
          "Contatos"
        ],
        "summary": "Grava um campo personalizado",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "key",
                  "value"
                ],
                "properties": {
                  "key": {
                    "type": "string"
                  },
                  "value": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "key": "plano",
                "value": "Ultra"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campo gravado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "key": "plano",
                  "value": "Ultra"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Grava um campo personalizado sozinho, sem mexer nos outros. A chave\nprecisa existir em Campos personalizados. Mande `value: null` para limpar.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/contacts/field\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"key\": \"plano\",\n    \"value\": \"Ultra\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts/field\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"key\": \"plano\",\n    \"value\": \"Ultra\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/contacts/field\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"key\": \"plano\",\n        \"value\": \"Ultra\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts/field\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"key\":\"plano\",\"value\":\"Ultra\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/contacts-schema": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Metadados da organização",
        "description": "Tudo que a organização tem cadastrado e que você precisa conhecer antes de\ngravar um contato: campos personalizados, etiquetas, funis com as etapas,\nmembros da equipe e números conectados.\n\nChame uma vez e guarde. Consultar isto evita o `400 unknown_fields` de\nquem inventou o nome de um campo.\n",
        "responses": {
          "200": {
            "description": "Metadados da organização",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgMetadata"
                },
                "example": {
                  "org": {
                    "id": "c0a80101-0000-4000-8000-000000000000",
                    "name": "Clínica Bem Estar"
                  },
                  "custom_fields": [
                    {
                      "key": "plano",
                      "label": "Plano",
                      "type": "select",
                      "options": [
                        "Basico",
                        "Premium",
                        "Ultra"
                      ],
                      "placeholder": null
                    }
                  ],
                  "tags": [
                    {
                      "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                      "name": "Lead quente",
                      "color": "#22D650"
                    }
                  ],
                  "assignable_users": [
                    {
                      "email": "paula@clinicabemestar.com.br",
                      "name": "Paula Ribeiro",
                      "role": "atendente"
                    }
                  ],
                  "whatsapp_connections": [
                    {
                      "id": "c0a80101-4444-4444-8444-444444444444",
                      "display_name": "Clínica Bem Estar",
                      "phone_number_id": "109876543210987"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/contacts-schema\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/contacts-schema\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/contacts-schema\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/contacts-schema\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations": {
      "get": {
        "tags": [
          "Conversas"
        ],
        "summary": "Lista conversas",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "resolved",
                "archived"
              ]
            },
            "description": "Filtra por situação."
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "web",
                "embed",
                "whatsapp",
                "api"
              ]
            },
            "description": "Filtra por canal de origem."
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Conversas atendidas por um agente específico."
          },
          {
            "name": "connection_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Conversas de um número de WhatsApp específico."
          },
          {
            "name": "contact_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Conversas de um contato específico."
          },
          {
            "name": "assigned_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "UUID de quem assumiu, ou `none` para as que ninguém assumiu."
          },
          {
            "name": "handoff",
            "in": "query",
            "description": "`pending` traz quem espera atendente",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "awaiting_reply",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "`true` traz só as que estão esperando resposta da sua equipe."
          },
          {
            "name": "sentiment",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "positive",
                "neutral",
                "negative"
              ]
            },
            "description": "Filtra pelo humor detectado na conversa."
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Etiqueta de conversa, por nome ou id."
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Telefone do cliente, em qualquer formato."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de conversas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-2222-4222-8222-222222222222",
                      "status": "open",
                      "channel": "whatsapp",
                      "contact": {
                        "id": "c0a80101-1111-4111-8111-111111111111",
                        "name": "Marina Alves",
                        "phone": "5511987654321"
                      },
                      "agent": {
                        "id": "c0a80101-3333-4333-8333-333333333333",
                        "name": "Recepção Bem Estar",
                        "status": "active",
                        "type": "ai"
                      },
                      "connection_id": "c0a80101-4444-4444-8444-444444444444",
                      "user": {
                        "name": "Marina Alves",
                        "email": null,
                        "phone": "5511987654321",
                        "metadata": null
                      },
                      "tags": [],
                      "awaiting_reply": true,
                      "bot_paused_until": null,
                      "takeover": null,
                      "handoff": {
                        "requested_at": "2026-09-05T18:40:00Z",
                        "reason": "Cliente pediu falar com humano"
                      },
                      "resolved": null,
                      "rating": null,
                      "sentiment": {
                        "label": "neutral",
                        "score": 0.1,
                        "reason": null,
                        "analyzed_at": "2026-09-05T18:41:00Z"
                      },
                      "referral": null,
                      "created_at": "2026-09-05T18:30:00Z",
                      "last_message_at": "2026-09-05T18:41:00Z",
                      "last_inbound_at": "2026-09-05T18:41:00Z",
                      "last_assistant_message_at": "2026-09-05T18:39:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As conversas da organização, da que teve movimento mais recente para a\nmais antiga.\n\nDois filtros resolvem a maioria dos casos: `handoff=pending` traz quem\nestá esperando atendente humano, e `awaiting_reply=true` traz quem falou\npor último e não foi respondido.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/conversations\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/conversations\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Conversas"
        ],
        "summary": "Uma conversa",
        "responses": {
          "200": {
            "description": "Conversa",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "contact": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "agent": {
                    "id": "c0a80101-3333-4333-8333-333333333333",
                    "name": "Recepção Bem Estar",
                    "status": "active",
                    "type": "ai"
                  },
                  "connection_id": "c0a80101-4444-4444-8444-444444444444",
                  "user": {
                    "name": "Marina Alves",
                    "email": null,
                    "phone": "5511987654321",
                    "metadata": null
                  },
                  "tags": [],
                  "awaiting_reply": true,
                  "created_at": "2026-09-05T18:30:00Z",
                  "last_message_at": "2026-09-05T18:41:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Uma conversa, com contato, agente, situação, transbordo, avaliação, humor e a origem do anúncio quando ela veio de um Click to WhatsApp.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/conversations/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/messages": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Conversas"
        ],
        "summary": "Mensagens da conversa",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de mensagens",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-9999-4999-8999-999999999991",
                      "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                      "role": "user",
                      "content": "Bom dia, gostaria de agendar uma avaliação.",
                      "file": null,
                      "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyMQ",
                      "delivery": {
                        "status": null,
                        "delivered_at": null,
                        "read_at": null,
                        "failed_reason": null
                      },
                      "reply_to_message_id": null,
                      "reactions": [],
                      "sent_by": null,
                      "handled_by_agent_id": null,
                      "source": null,
                      "created_at": "2026-09-05T18:30:00Z"
                    },
                    {
                      "id": "c0a80101-9999-4999-8999-999999999992",
                      "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                      "role": "assistant",
                      "content": "Bom dia, Marina! Temos horário na quinta às 14h. Serve?",
                      "file": null,
                      "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyMg",
                      "delivery": {
                        "status": "read",
                        "delivered_at": "2026-09-05T18:39:05Z",
                        "read_at": "2026-09-05T18:40:00Z",
                        "failed_reason": null
                      },
                      "reply_to_message_id": null,
                      "reactions": [],
                      "sent_by": null,
                      "handled_by_agent_id": "c0a80101-3333-4333-8333-333333333333",
                      "source": null,
                      "created_at": "2026-09-05T18:39:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As mensagens da conversa, da mais antiga para a mais recente, com o status\nde entrega de cada uma quando o canal informa.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/conversations/{id}/messages\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/messages\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/messages\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/messages\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Responde dentro da conversa",
        "description": "Responde dentro de uma conversa que já existe. Aceita os mesmos doze tipos\ndo `POST /messages`, sem precisar informar destino: a conversa já diz para\nquem vai.\n\nA mensagem aparece na linha do tempo do inbox, como qualquer resposta da\nequipe.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessage"
              },
              "example": {
                "type": "text",
                "text": "Perfeito, Marina. Agendei para quinta às 14h."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado do envio",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendResult"
                },
                "example": {
                  "id": "c0a80101-9999-4999-8999-999999999993",
                  "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyMw",
                  "status": "sent",
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/messages\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"text\",\n    \"text\": \"Perfeito, Marina. Agendei para quinta às 14h.\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/messages\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"type\": \"text\",\n    \"text\": \"Perfeito, Marina. Agendei para quinta às 14h.\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/messages\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"type\": \"text\",\n        \"text\": \"Perfeito, Marina. Agendei para quinta às 14h.\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/messages\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"type\":\"text\",\"text\":\"Perfeito, Marina. Agendei para quinta às 14h.\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Conversas"
        ],
        "summary": "Eventos de conversão da conversa",
        "responses": {
          "200": {
            "description": "Lista de eventos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationEventList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-ffff-4fff-8fff-ffffffffffff",
                      "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                      "name": "agendamento_marcado",
                      "metadata": {
                        "data": "2026-09-11"
                      },
                      "created_at": "2026-09-05T18:41:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os eventos de conversão que o agente detectou nesta conversa, como um\nagendamento marcado ou uma proposta aceita. Quais eventos existem é\nconfiguração de cada agente.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/conversations/{id}/events\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/events\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/events\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/events\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/export": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Conversas"
        ],
        "summary": "Transcrição da conversa",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "markdown"
              ],
              "default": "json"
            },
            "description": "`json` (padrão) ou `markdown`."
          }
        ],
        "responses": {
          "200": {
            "description": "Transcrição",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationExport"
                },
                "example": {
                  "conversation": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp",
                    "created_at": "2026-09-05T18:30:00Z"
                  },
                  "messages": [
                    {
                      "id": "c0a80101-9999-4999-8999-999999999991",
                      "role": "user",
                      "content": "Bom dia, gostaria de agendar uma avaliação.",
                      "created_at": "2026-09-05T18:30:00Z"
                    }
                  ],
                  "message_count": 1,
                  "exported_at": "2026-09-08T12:20:00Z"
                }
              },
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "A conversa inteira num arquivo só, para anexar num chamado, num processo\nou num relatório. Em `markdown` sai legível para uma pessoa; em `json`,\npara outro sistema.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/conversations/{id}/export\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/export\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/export\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/export\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/assign": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Define quem atende a conversa",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "user_email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              },
              "example": {
                "user_email": "paula@clinicabemestar.com.br"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "takeover": {
                    "user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd",
                    "at": "2026-09-08T12:22:00Z"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Coloca um membro da equipe como responsável pela conversa. A IA para de\nresponder nela até alguém devolver com `/release`.\n\nInforme `user_id` ou `user_email`.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/assign\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_email\": \"paula@clinicabemestar.com.br\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/assign\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"user_email\": \"paula@clinicabemestar.com.br\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/assign\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"user_email\": \"paula@clinicabemestar.com.br\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/assign\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"user_email\":\"paula@clinicabemestar.com.br\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/release": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Devolve a conversa para a IA",
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "takeover": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Tira o responsável humano e devolve a conversa para a IA, que volta a responder na próxima mensagem do cliente.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/release\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/release\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/release\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/release\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/pause-ai": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Silencia a IA por um tempo",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "minutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 43200,
                    "default": 60
                  }
                }
              },
              "example": {
                "minutes": 30
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "bot_paused_until": "2026-09-08T12:52:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Silencia a IA nesta conversa por um tempo, sem passar o atendimento para\nninguém. Serve para quem vai responder na mão agora e não quer o agente\nfalando junto.\n\nSem `minutes`, o padrão são 60 minutos.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/pause-ai\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"minutes\": 30\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/pause-ai\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"minutes\": 30\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/pause-ai\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"minutes\": 30\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/pause-ai\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"minutes\":30}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/resume-ai": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Volta a IA a responder",
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "bot_paused_until": null
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Cancela a pausa e devolve a palavra à IA na hora.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/resume-ai\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/resume-ai\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/resume-ai\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/resume-ai\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/resolve": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Encerra a conversa",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "user_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Quem encerrou."
                  }
                }
              },
              "example": {
                "user_email": "paula@clinicabemestar.com.br"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "resolved",
                  "channel": "whatsapp",
                  "resolved": {
                    "at": "2026-09-08T12:25:00Z",
                    "by": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Encerra a conversa. Ela sai da fila do inbox e passa a contar como\nresolvida nos números. Se o cliente escrever de novo, ela reabre sozinha.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/resolve\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"user_email\": \"paula@clinicabemestar.com.br\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/resolve\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"user_email\": \"paula@clinicabemestar.com.br\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/resolve\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"user_email\": \"paula@clinicabemestar.com.br\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/resolve\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"user_email\":\"paula@clinicabemestar.com.br\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/reopen": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Reabre a conversa",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Corpo opcional; hoje nenhum campo é usado."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "resolved": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Reabre uma conversa encerrada, sem esperar o cliente escrever.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/reopen\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/reopen\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({}),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/reopen\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/reopen\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/handoff": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Pede atendente humano",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "reason": "Cliente relatou cobrança indevida"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conversa atualizada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "c0a80101-2222-4222-8222-222222222222",
                  "status": "open",
                  "channel": "whatsapp",
                  "handoff": {
                    "requested_at": "2026-09-08T12:27:00Z",
                    "reason": "Cliente relatou cobrança indevida"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Marca que esta conversa precisa de atendente humano. Ela passa a aparecer\nno filtro `handoff=pending` e dispara o evento\n`conversation.handoff_requested`.\n\nUse quando o seu sistema descobrir algo que a IA não resolve, como um\ncliente em atraso ou um caso jurídico.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/handoff\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"reason\": \"Cliente relatou cobrança indevida\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/handoff\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"reason\": \"Cliente relatou cobrança indevida\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/handoff\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"reason\": \"Cliente relatou cobrança indevida\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/handoff\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"reason\":\"Cliente relatou cobrança indevida\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/conversations/{id}/tags": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Conversas"
        ],
        "summary": "Aplica etiqueta na conversa",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "tag": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "tag": "Urgente"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Etiqueta aplicada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                  "tag": {
                    "id": "c0a80101-abab-4aba-8aba-abababababab",
                    "name": "Urgente",
                    "created": true
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Aplica uma etiqueta de conversa, criando a etiqueta se ela ainda não existir. Etiqueta de conversa é diferente de etiqueta de contato.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/conversations/{id}/tags\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tag\": \"Urgente\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/tags\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"tag\": \"Urgente\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/tags\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"tag\": \"Urgente\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/tags\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"tag\":\"Urgente\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Conversas"
        ],
        "summary": "Remove etiqueta da conversa",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag"
                ],
                "properties": {
                  "tag": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "tag": "Urgente"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Etiqueta removida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Tira uma etiqueta da conversa.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/conversations/{id}/tags\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"tag\": \"Urgente\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/conversations/{id}/tags\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"tag\": \"Urgente\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/conversations/{id}/tags\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"tag\": \"Urgente\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/conversations/{id}/tags\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"tag\":\"Urgente\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/messages": {
      "get": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Busca mensagens",
        "description": "Busca mensagens de conversa e disparos avulsos no mesmo lugar. Exige um\nfiltro: `conversation_id` traz as mensagens daquela conversa, `contact_id`\ntraz os disparos feitos para um contato, e `wamid` traz a mensagem\nespecífica.\n\nÉ por aqui que você confere se aquele envio chegou, foi lido ou falhou.\nPara varrer tudo, use `GET /conversations` e depois\n`GET /conversations/{id}/messages`.\n",
        "parameters": [
          {
            "name": "wamid",
            "in": "query",
            "description": "Id da mensagem no WhatsApp",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "conversation_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Mensagens de uma conversa."
          },
          {
            "name": "contact_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Disparos feitos para um contato."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Mensagem, ou lista",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageOrSendList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-9999-4999-8999-999999999994",
                      "conversation_id": null,
                      "kind": "template",
                      "to": "5511987654321",
                      "contact_id": "c0a80101-1111-4111-8111-111111111111",
                      "connection_id": "c0a80101-4444-4444-8444-444444444444",
                      "template": {
                        "name": "confirmacao_consulta",
                        "language_code": "pt_BR",
                        "body_params": [
                          "Marina",
                          "quinta às 14h"
                        ]
                      },
                      "content": null,
                      "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyNA",
                      "delivery": {
                        "status": "delivered",
                        "sent_at": "2026-09-08T09:00:00Z",
                        "delivered_at": "2026-09-08T09:00:04Z",
                        "read_at": null,
                        "failed_reason": null
                      },
                      "idempotency_key": "consulta-8891-lembrete",
                      "created_at": "2026-09-08T09:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/messages\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/messages\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/messages\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/messages\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Envia uma mensagem de qualquer tipo",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Retry com a mesma chave não reenvia."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessage"
              },
              "example": {
                "type": "template",
                "to": "+5511987654321",
                "connection_id": "c0a80101-4444-4444-8444-444444444444",
                "template_name": "confirmacao_consulta",
                "language_code": "pt_BR",
                "body_params": [
                  "Marina",
                  "quinta às 14h"
                ],
                "contact": {
                  "name": "Marina Alves"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado do envio. Recusa da Meta também vem aqui, com\n`status: \"failed\"` e o motivo em `error`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendResult"
                },
                "example": {
                  "id": "c0a80101-9999-4999-8999-999999999994",
                  "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyNA",
                  "status": "sent",
                  "conversation_id": null,
                  "contact_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "O envio de mensagem, para todos os tipos. O campo `type` decide o resto do\ncorpo: `text` usa `text`, `template` usa `template_name` e `body_params`,\nmídia usa `media`, e os interativos usam `body` mais o campo do formato.\n\nFora da janela de 24 horas desde a última mensagem do cliente, o WhatsApp\nsó aceita template aprovado. Texto livre nesse caso volta com `200` e\n`status: failed`.\n\nMande sempre o header `Idempotency-Key`. Se a rede cair e o seu código\ntentar de novo, a mensagem não sai duas vezes.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/messages\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"template\",\n    \"to\": \"+5511987654321\",\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n    \"template_name\": \"confirmacao_consulta\",\n    \"language_code\": \"pt_BR\",\n    \"body_params\": [\n      \"Marina\",\n      \"quinta às 14h\"\n    ],\n    \"contact\": {\n      \"name\": \"Marina Alves\"\n    }\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/messages\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"type\": \"template\",\n    \"to\": \"+5511987654321\",\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n    \"template_name\": \"confirmacao_consulta\",\n    \"language_code\": \"pt_BR\",\n    \"body_params\": [\n      \"Marina\",\n      \"quinta às 14h\"\n    ],\n    \"contact\": {\n      \"name\": \"Marina Alves\"\n    }\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/messages\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"type\": \"template\",\n        \"to\": \"+5511987654321\",\n        \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n        \"template_name\": \"confirmacao_consulta\",\n        \"language_code\": \"pt_BR\",\n        \"body_params\": [\n            \"Marina\",\n            \"quinta às 14h\"\n        ],\n        \"contact\": {\n            \"name\": \"Marina Alves\"\n        }\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/messages\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"type\":\"template\",\"to\":\"+5511987654321\",\"connection_id\":\"c0a80101-4444-4444-8444-444444444444\",\"template_name\":\"confirmacao_consulta\",\"language_code\":\"pt_BR\",\"body_params\":[\"Marina\",\"quinta às 14h\"],\"contact\":{\"name\":\"Marina Alves\"}}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/messages/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Uma mensagem, ou um disparo avulso",
        "responses": {
          "200": {
            "description": "Mensagem",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiSend"
                },
                "example": {
                  "id": "c0a80101-9999-4999-8999-999999999994",
                  "conversation_id": null,
                  "kind": "template",
                  "to": "5511987654321",
                  "connection_id": "c0a80101-4444-4444-8444-444444444444",
                  "template": {
                    "name": "confirmacao_consulta",
                    "language_code": "pt_BR",
                    "body_params": [
                      "Marina",
                      "quinta às 14h"
                    ]
                  },
                  "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyNA",
                  "delivery": {
                    "status": "read",
                    "sent_at": "2026-09-08T09:00:00Z",
                    "delivered_at": "2026-09-08T09:00:04Z",
                    "read_at": "2026-09-08T09:12:00Z",
                    "failed_reason": null
                  },
                  "created_at": "2026-09-08T09:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Uma mensagem de conversa ou um disparo avulso, pelo identificador que o envio devolveu.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/messages/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/messages/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/messages/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/messages/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/agents": {
      "get": {
        "tags": [
          "Agentes"
        ],
        "summary": "Lista agentes",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por situação do agente."
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "`ai` para agente de IA, `flow` para agente de botões."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca pelo nome."
          },
          {
            "name": "include_archived",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "`true` inclui os arquivados."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de agentes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-3333-4333-8333-333333333333",
                      "name": "Recepção Bem Estar",
                      "description": "Agenda consultas e responde dúvidas sobre tratamentos.",
                      "status": "active",
                      "type": "ai",
                      "public_slug": "recepcao-bem-estar",
                      "public_url": "https://app.wevi.chat/chat/recepcao-bem-estar",
                      "model": "claude-sonnet-4-6",
                      "temperature": 0.7,
                      "conversion_events": [
                        {
                          "name": "agendamento_marcado"
                        }
                      ],
                      "features": {
                        "sentiment": true,
                        "handoff": true,
                        "business_hours": false,
                        "business_hours_mode": null
                      },
                      "created_at": "2026-06-01T09:00:00Z",
                      "updated_at": "2026-09-02T11:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os agentes da organização, com modelo, canal e o que cada um sabe detectar na conversa.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/agents\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/agents\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/agents\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/agents\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/agents/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathIdOrSlug"
        }
      ],
      "get": {
        "tags": [
          "Agentes"
        ],
        "summary": "Um agente, por id ou slug público",
        "responses": {
          "200": {
            "description": "Agente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                },
                "example": {
                  "id": "c0a80101-3333-4333-8333-333333333333",
                  "name": "Recepção Bem Estar",
                  "status": "active",
                  "type": "ai",
                  "model": "claude-sonnet-4-6",
                  "system_prompt": "Você é a recepção da Clínica Bem Estar...",
                  "features": {
                    "sentiment": true,
                    "handoff": true,
                    "business_hours": false,
                    "business_hours_mode": null
                  },
                  "created_at": "2026-06-01T09:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um agente, pelo identificador interno ou pelo slug público. O prompt do sistema vem junto, então trate a resposta como conteúdo interno.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/agents/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/agents/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/agents/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/agents/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/agents/{id}/chat": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathIdOrSlug"
        }
      ],
      "post": {
        "tags": [
          "Agentes"
        ],
        "summary": "Conversa com o agente",
        "description": "Conversa com um agente de IA sem passar pelo WhatsApp. A resposta vem no\ncorpo, e a conversa fica registrada no inbox como qualquer outra, no canal\n`api`.\n\nServe para colocar o agente dentro do seu produto: um chat no seu app, um\nassistente no seu site, ou um canal que a gente ainda não tem.\n\nGuarde o `conversation_id` da primeira resposta e mande nas seguintes, ou\nuse `external_user_id` com o identificador do usuário no seu sistema e\ndeixe a continuidade por nossa conta.\n\nO agente usa a chave de IA da sua organização, então o consumo aparece\nnormalmente no painel. Sem chave configurada, a resposta é `402`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentChatRequest"
              },
              "example": {
                "message": "Quanto custa uma limpeza?",
                "external_user_id": "usuario-4471",
                "user": {
                  "name": "Marina Alves",
                  "email": "marina.alves@exemplo.com.br"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resposta do agente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentChatResponse"
                },
                "example": {
                  "conversation_id": "c0a80101-2222-4222-8222-222222222223",
                  "conversation_created": true,
                  "message": {
                    "id": "c0a80101-9999-4999-8999-999999999995",
                    "role": "assistant",
                    "content": "A limpeza sai por R$ 180. Quer que eu veja um horário?"
                  },
                  "handoff": null
                }
              }
            }
          },
          "202": {
            "description": "Em processamento, ou conversa com humano"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/agents/{id}/chat\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"message\": \"Quanto custa uma limpeza?\",\n    \"external_user_id\": \"usuario-4471\",\n    \"user\": {\n      \"name\": \"Marina Alves\",\n      \"email\": \"marina.alves@exemplo.com.br\"\n    }\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/agents/{id}/chat\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"message\": \"Quanto custa uma limpeza?\",\n    \"external_user_id\": \"usuario-4471\",\n    \"user\": {\n      \"name\": \"Marina Alves\",\n      \"email\": \"marina.alves@exemplo.com.br\"\n    }\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/agents/{id}/chat\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"message\": \"Quanto custa uma limpeza?\",\n        \"external_user_id\": \"usuario-4471\",\n        \"user\": {\n            \"name\": \"Marina Alves\",\n            \"email\": \"marina.alves@exemplo.com.br\"\n        }\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/agents/{id}/chat\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"message\":\"Quanto custa uma limpeza?\",\"external_user_id\":\"usuario-4471\",\"user\":{\"name\":\"Marina Alves\",\"email\":\"marina.alves@exemplo.com.br\"}}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/agents/{id}/knowledge/documents": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathIdOrSlug"
        }
      ],
      "get": {
        "tags": [
          "Agentes"
        ],
        "summary": "Documentos da base de conhecimento",
        "responses": {
          "200": {
            "description": "Lista de documentos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeDocumentList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-1a1a-4a1a-8a1a-1a1a1a1a1a1a",
                      "name": "Tabela de preços 2026",
                      "source_url": null,
                      "status": "ready",
                      "chunk_count": 42,
                      "created_at": "2026-08-01T10:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os documentos que alimentam as respostas deste agente, com o status da indexação de cada um.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Agentes"
        ],
        "summary": "Adiciona um documento",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "content"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "content": {
                    "type": "string",
                    "description": "Texto do documento. Máximo 2 MB."
                  },
                  "source_url": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "name": "Tabela de preços 2026",
                "content": "Limpeza: R$ 180. Clareamento: R$ 890...",
                "format": "text"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Documento criado; a indexação roda em segundo plano",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeDocument"
                },
                "example": {
                  "id": "c0a80101-1a1a-4a1a-8a1a-1a1a1a1a1a1a",
                  "name": "Tabela de preços 2026",
                  "source_url": null,
                  "status": "pending",
                  "chunk_count": null,
                  "created_at": "2026-09-08T12:30:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Adiciona um documento à base de conhecimento do agente, por texto direto\nou por URL. A indexação roda em segundo plano: o documento nasce\n`pending` e vira `ready` quando terminar.\n\nServe para manter a base sincronizada com o seu CMS ou repositório, sem\nninguém subir arquivo na mão.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Tabela de preços 2026\",\n    \"content\": \"Limpeza: R$ 180. Clareamento: R$ 890...\",\n    \"format\": \"text\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Tabela de preços 2026\",\n    \"content\": \"Limpeza: R$ 180. Clareamento: R$ 890...\",\n    \"format\": \"text\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"name\": \"Tabela de preços 2026\",\n        \"content\": \"Limpeza: R$ 180. Clareamento: R$ 890...\",\n        \"format\": \"text\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"name\":\"Tabela de preços 2026\",\"content\":\"Limpeza: R$ 180. Clareamento: R$ 890...\",\"format\":\"text\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/agents/{id}/knowledge/documents/{document_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathIdOrSlug"
        },
        {
          "name": "document_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "delete": {
        "tags": [
          "Agentes"
        ],
        "summary": "Remove um documento",
        "responses": {
          "200": {
            "description": "Documento removido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Remove o documento e os trechos indexados dele. O agente para de usar aquele conteúdo na resposta seguinte.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents/{document_id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents/{document_id}\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents/{document_id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/agents/{id}/knowledge/documents/{document_id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/connections": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Números de WhatsApp conectados",
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Só os números atendidos por um agente específico."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de conexões",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-4444-4444-8444-444444444444",
                      "display_name": "Clínica Bem Estar",
                      "phone_number": "+55 11 3000-0000",
                      "phone_number_id": "109876543210987",
                      "waba_id": "209876543210987",
                      "verified_name": "Clínica Bem Estar",
                      "quality_rating": "GREEN",
                      "agent_id": "c0a80101-3333-4333-8333-333333333333",
                      "connected_via": "embedded_signup",
                      "is_coexistence": false,
                      "catalog_id": null,
                      "config_error": null,
                      "subscribed_at": "2026-06-01T09:30:00Z",
                      "created_at": "2026-06-01T09:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os números de WhatsApp conectados, com a nota de qualidade que a Meta dá a\ncada um e o erro de configuração, quando existe.\n\nSe a organização tem um número só, você não precisa mandar `connection_id`\nnos envios.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/connections\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/connections\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/connections\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/connections\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/connections/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Uma conexão",
        "responses": {
          "200": {
            "description": "Conexão",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Connection"
                },
                "example": {
                  "id": "c0a80101-4444-4444-8444-444444444444",
                  "display_name": "Clínica Bem Estar",
                  "phone_number": "+55 11 3000-0000",
                  "quality_rating": "GREEN",
                  "config_error": null,
                  "created_at": "2026-06-01T09:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um número conectado.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/connections/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/connections/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/connections/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/connections/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/templates": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Templates de WhatsApp",
        "parameters": [
          {
            "name": "connection_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Templates de um número específico."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra pelo status na Meta."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra pela categoria."
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca pelo nome do template."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-5555-4555-8555-555555555555",
                      "meta_id": "1234567890123456",
                      "name": "confirmacao_consulta",
                      "category": "UTILITY",
                      "language_code": "pt_BR",
                      "status": "APPROVED",
                      "connection_id": "c0a80101-4444-4444-8444-444444444444",
                      "header": null,
                      "body": "Olá {{1}}! Sua consulta está confirmada para {{2}}.",
                      "footer": "Clínica Bem Estar",
                      "buttons": [],
                      "body_variables": 2,
                      "rejection_reason": null,
                      "created_at": "2026-07-10T14:00:00Z",
                      "updated_at": "2026-07-10T18:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os templates de mensagem da organização, com o status que a Meta deu a\ncada um. Só template `APPROVED` pode ser enviado.\n\nO campo `body_variables` diz quantos itens `body_params` precisa ter no\nenvio. Conferir isso antes evita o envio recusado.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/templates\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/templates\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/templates\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/templates\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Configuração"
        ],
        "summary": "Cria e submete um template à Meta",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateCreate"
              },
              "example": {
                "connection_id": "c0a80101-4444-4444-8444-444444444444",
                "name": "lembrete_retorno",
                "category": "UTILITY",
                "language_code": "pt_BR",
                "body_text": "Oi {{1}}, faz {{2}} meses desde a sua última visita. Quer marcar um retorno?",
                "footer_text": "Clínica Bem Estar"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Template enviado para aprovação",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                },
                "example": {
                  "id": "c0a80101-5555-4555-8555-555555555556",
                  "meta_id": "1234567890123457",
                  "name": "lembrete_retorno",
                  "category": "UTILITY",
                  "status": "PENDING",
                  "body_variables": 2,
                  "created_at": "2026-09-08T12:35:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Cria o template e submete à Meta na mesma chamada. Ele nasce `PENDING` e a\naprovação leva de minutos a algumas horas.\n\nAssine o evento `template.status_changed` para saber quando ele sair,\naprovado ou recusado, em vez de ficar consultando.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/templates\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n    \"name\": \"lembrete_retorno\",\n    \"category\": \"UTILITY\",\n    \"language_code\": \"pt_BR\",\n    \"body_text\": \"Oi {{1}}, faz {{2}} meses desde a sua última visita. Quer marcar um retorno?\",\n    \"footer_text\": \"Clínica Bem Estar\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/templates\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n    \"name\": \"lembrete_retorno\",\n    \"category\": \"UTILITY\",\n    \"language_code\": \"pt_BR\",\n    \"body_text\": \"Oi {{1}}, faz {{2}} meses desde a sua última visita. Quer marcar um retorno?\",\n    \"footer_text\": \"Clínica Bem Estar\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/templates\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n        \"name\": \"lembrete_retorno\",\n        \"category\": \"UTILITY\",\n        \"language_code\": \"pt_BR\",\n        \"body_text\": \"Oi {{1}}, faz {{2}} meses desde a sua última visita. Quer marcar um retorno?\",\n        \"footer_text\": \"Clínica Bem Estar\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/templates\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"connection_id\":\"c0a80101-4444-4444-8444-444444444444\",\"name\":\"lembrete_retorno\",\"category\":\"UTILITY\",\"language_code\":\"pt_BR\",\"body_text\":\"Oi {{1}}, faz {{2}} meses desde a sua última visita. Quer marcar um retorno?\",\"footer_text\":\"Clínica Bem Estar\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/templates/sync": {
      "post": {
        "tags": [
          "Configuração"
        ],
        "summary": "Sincroniza templates com a Meta",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "connection_id"
                ],
                "properties": {
                  "connection_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              },
              "example": {
                "connection_id": "c0a80101-4444-4444-8444-444444444444"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado da sincronização",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "synced": 12,
                  "created": 1,
                  "updated": 3
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Puxa da Meta o status atual de todos os templates do número. Use quando\ndesconfiar que a lista aqui está atrasada; no dia a dia, o evento\n`template.status_changed` já avisa.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/templates/sync\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/templates/sync\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/templates/sync\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/templates/sync\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"connection_id\":\"c0a80101-4444-4444-8444-444444444444\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/templates/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Um template, por id da Wevichat ou Meta ID",
        "responses": {
          "200": {
            "description": "Template",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                },
                "example": {
                  "id": "c0a80101-5555-4555-8555-555555555555",
                  "name": "confirmacao_consulta",
                  "status": "APPROVED",
                  "body": "Olá {{1}}! Sua consulta está confirmada para {{2}}.",
                  "body_variables": 2
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um template, pelo identificador da Wevichat ou pelo Meta ID.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/templates/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/templates/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/templates/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/templates/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Configuração"
        ],
        "summary": "Apaga o template na Meta e aqui",
        "responses": {
          "200": {
            "description": "Template apagado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "deleted": true,
                  "id": "c0a80101-5555-4555-8555-555555555555"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Apaga o template na Meta e aqui. Campanha que ainda dependia dele para de funcionar, então confira antes.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/templates/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/templates/{id}\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/templates/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/templates/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/tags": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Etiquetas de contato ou de conversa",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "contact",
                "conversation"
              ],
              "default": "contact"
            },
            "description": "`contact` (padrão) ou `conversation`."
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de etiquetas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                      "name": "Lead quente",
                      "color": "#22D650",
                      "type": "contact",
                      "created_at": "2026-06-02T10:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As etiquetas da organização. As de contato e as de conversa são conjuntos separados.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/tags\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/tags\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/tags\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/tags\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/pipelines": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Funis e suas etapas",
        "responses": {
          "200": {
            "description": "Lista de funis",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PipelineList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
                      "name": "Funil de vendas",
                      "position": 0,
                      "is_default": true,
                      "auto_enroll": false,
                      "created_at": "2026-06-01T09:00:00Z",
                      "stages": [
                        {
                          "id": "c0a80101-cccc-4ccc-8ccc-ccccccccccc1",
                          "name": "Contato",
                          "position": 0,
                          "color": "#9CA3AF"
                        },
                        {
                          "id": "c0a80101-cccc-4ccc-8ccc-cccccccccccc",
                          "name": "Proposta enviada",
                          "position": 1,
                          "color": "#22D650"
                        }
                      ]
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os funis, com as etapas na ordem em que aparecem no painel. Use os nomes daqui em `POST /contacts/stage`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/pipelines\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/pipelines\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/pipelines\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/pipelines\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/fields": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Campos personalizados de contato",
        "responses": {
          "200": {
            "description": "Lista de campos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldList"
                },
                "example": {
                  "data": [
                    {
                      "key": "plano",
                      "label": "Plano",
                      "type": "select",
                      "options": [
                        "Basico",
                        "Premium",
                        "Ultra"
                      ],
                      "placeholder": null,
                      "position": 0
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os campos personalizados de contato. As chaves daqui são as únicas aceitas em `fields`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/fields\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/fields\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/fields\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/fields\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/users": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Membros da organização",
        "parameters": [
          {
            "name": "role",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por papel."
          },
          {
            "name": "assignable",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "`true` traz só quem pode receber conversa ou carteira."
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de membros",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd",
                      "name": "Paula Ribeiro",
                      "email": "paula@clinicabemestar.com.br",
                      "role": "atendente",
                      "is_owner": false,
                      "member_since": "2026-06-01T09:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os membros da organização, com o papel de cada um. É daqui que sai o email para atribuir carteira ou conversa.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/users\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/users\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/users\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/users\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/quick-replies": {
      "get": {
        "tags": [
          "Configuração"
        ],
        "summary": "Respostas rápidas da equipe",
        "responses": {
          "200": {
            "description": "Lista de respostas rápidas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuickReplyList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-2b2b-4b2b-8b2b-2b2b2b2b2b2b",
                      "shortcut": "/horario",
                      "content": "Atendemos de segunda a sexta, das 8h às 18h."
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As respostas rápidas que a equipe usa no inbox. Serve para reaproveitar o mesmo texto no seu sistema.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/quick-replies\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/quick-replies\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/quick-replies\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/quick-replies\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/campaigns": {
      "get": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Lista campanhas",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por situação da campanha."
          },
          {
            "name": "connection_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Campanhas de um número específico."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de campanhas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-6666-4666-8666-666666666666",
                      "name": "Retorno semestral",
                      "status": "completed",
                      "connection_id": "c0a80101-4444-4444-8444-444444444444",
                      "template": {
                        "name": "lembrete_retorno",
                        "language_code": "pt_BR",
                        "body_params": [],
                        "header_image_url": null
                      },
                      "audience": {
                        "tag": "Inativo"
                      },
                      "open_conversation": "on_reply",
                      "metrics": {
                        "total_recipients": 320,
                        "sent": 318,
                        "delivered": 305,
                        "read": 214,
                        "failed": 2
                      },
                      "scheduled_at": null,
                      "started_at": "2026-09-02T09:00:00Z",
                      "completed_at": "2026-09-02T09:14:00Z",
                      "created_at": "2026-09-01T16:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As campanhas da organização, com as métricas de entrega de cada uma.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/campaigns\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/campaigns\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Cria uma campanha como rascunho",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignCreate"
              },
              "example": {
                "name": "Retorno semestral",
                "connection_id": "c0a80101-4444-4444-8444-444444444444",
                "template_name": "lembrete_retorno",
                "language_code": "pt_BR",
                "audience_filter": {
                  "tag": "Inativo"
                },
                "open_conversation": "on_reply"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Campanha criada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "example": {
                  "id": "c0a80101-6666-4666-8666-666666666666",
                  "name": "Retorno semestral",
                  "status": "draft",
                  "metrics": {
                    "total_recipients": 320,
                    "sent": 0,
                    "delivered": 0,
                    "read": 0,
                    "failed": 0
                  },
                  "created_at": "2026-09-08T12:40:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Cria a campanha como rascunho. Nada é enviado aqui: depois de conferir a\naudiência em `GET /campaigns/{id}`, dispare com `/start` ou marque hora\ncom `/schedule`.\n\nDefina quem recebe por `audience` (lista de ids de contato) ou por\n`audience_filter` (etiqueta, funil ou etapa). Quem pediu opt-out fica de\nfora automaticamente.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/campaigns\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Retorno semestral\",\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n    \"template_name\": \"lembrete_retorno\",\n    \"language_code\": \"pt_BR\",\n    \"audience_filter\": {\n      \"tag\": \"Inativo\"\n    },\n    \"open_conversation\": \"on_reply\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Retorno semestral\",\n    \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n    \"template_name\": \"lembrete_retorno\",\n    \"language_code\": \"pt_BR\",\n    \"audience_filter\": {\n      \"tag\": \"Inativo\"\n    },\n    \"open_conversation\": \"on_reply\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/campaigns\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"name\": \"Retorno semestral\",\n        \"connection_id\": \"c0a80101-4444-4444-8444-444444444444\",\n        \"template_name\": \"lembrete_retorno\",\n        \"language_code\": \"pt_BR\",\n        \"audience_filter\": {\n            \"tag\": \"Inativo\"\n        },\n        \"open_conversation\": \"on_reply\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"name\":\"Retorno semestral\",\"connection_id\":\"c0a80101-4444-4444-8444-444444444444\",\"template_name\":\"lembrete_retorno\",\"language_code\":\"pt_BR\",\"audience_filter\":{\"tag\":\"Inativo\"},\"open_conversation\":\"on_reply\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/campaigns/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Uma campanha, com métricas",
        "responses": {
          "200": {
            "description": "Campanha",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "example": {
                  "id": "c0a80101-6666-4666-8666-666666666666",
                  "name": "Retorno semestral",
                  "status": "running",
                  "metrics": {
                    "total_recipients": 320,
                    "sent": 128,
                    "delivered": 120,
                    "read": 44,
                    "failed": 1
                  },
                  "started_at": "2026-09-08T12:45:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Uma campanha, com as métricas atualizadas. Durante o disparo, os números sobem aos poucos.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/campaigns/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/campaigns/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/campaigns/{id}/start": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Dispara a campanha",
        "responses": {
          "200": {
            "description": "Campanha em disparo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "example": {
                  "id": "c0a80101-6666-4666-8666-666666666666",
                  "status": "running",
                  "started_at": "2026-09-08T12:45:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Dispara a campanha agora. O envio acontece em lotes, respeitando o limite do número na Meta.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/campaigns/{id}/start\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns/{id}/start\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/campaigns/{id}/start\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns/{id}/start\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/campaigns/{id}/schedule": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Agenda a campanha",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "scheduled_at"
                ],
                "properties": {
                  "scheduled_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              },
              "example": {
                "scheduled_at": "2026-09-10T09:00:00Z"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campanha agendada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "example": {
                  "id": "c0a80101-6666-4666-8666-666666666666",
                  "status": "scheduled",
                  "scheduled_at": "2026-09-10T09:00:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Marca hora para o disparo. A campanha fica `scheduled` até lá.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/campaigns/{id}/schedule\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"scheduled_at\": \"2026-09-10T09:00:00Z\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns/{id}/schedule\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"scheduled_at\": \"2026-09-10T09:00:00Z\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/campaigns/{id}/schedule\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"scheduled_at\": \"2026-09-10T09:00:00Z\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns/{id}/schedule\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"scheduled_at\":\"2026-09-10T09:00:00Z\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/campaigns/{id}/cancel": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Cancela a campanha",
        "responses": {
          "200": {
            "description": "Campanha cancelada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Campaign"
                },
                "example": {
                  "id": "c0a80101-6666-4666-8666-666666666666",
                  "status": "cancelled",
                  "metrics": {
                    "total_recipients": 320,
                    "sent": 128,
                    "delivered": 120,
                    "read": 44,
                    "failed": 1
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Cancela a campanha. O que já saiu não volta: cancelar interrompe os lotes\nque ainda não foram enviados.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/campaigns/{id}/cancel\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns/{id}/cancel\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/campaigns/{id}/cancel\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns/{id}/cancel\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/campaigns/{id}/recipients": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Campanhas"
        ],
        "summary": "Destinatários da campanha",
        "description": "Quem recebeu, com o status de cada envio. É onde você vê quais números\nfalharam e por quê, para limpar a sua base.\n",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por situação do envio."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de destinatários",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignRecipientList"
                },
                "example": {
                  "data": [
                    {
                      "contact_id": "c0a80101-1111-4111-8111-111111111111",
                      "phone": "5511987654321",
                      "status": "delivered",
                      "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyNQ",
                      "error": null,
                      "sent_at": "2026-09-02T09:01:00Z"
                    },
                    {
                      "contact_id": null,
                      "phone": "5511900000000",
                      "status": "failed",
                      "wamid": null,
                      "error": "Número não existe no WhatsApp",
                      "sent_at": null
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/campaigns/{id}/recipients\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/campaigns/{id}/recipients\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/campaigns/{id}/recipients\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/campaigns/{id}/recipients\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/automations": {
      "get": {
        "tags": [
          "Automações"
        ],
        "summary": "Lista fluxos de automação",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por situação do fluxo."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de fluxos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-7777-4777-8777-777777777777",
                      "name": "Recuperação de orçamento",
                      "status": "active",
                      "connection_id": "c0a80101-4444-4444-8444-444444444444",
                      "trigger": {
                        "webhook_enabled": true,
                        "type": "webhook",
                        "tag_id": null,
                        "stage_id": null
                      },
                      "exit_conditions": null,
                      "re_entry_cooldown_hours": 720,
                      "node_count": 6,
                      "created_at": "2026-07-20T11:00:00Z",
                      "updated_at": "2026-08-30T15:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os fluxos de automação da organização. O token do webhook de cada fluxo é credencial e não aparece aqui.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/automations\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/automations\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/automations\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/automations\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/automations/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Automações"
        ],
        "summary": "Um fluxo",
        "responses": {
          "200": {
            "description": "Fluxo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Automation"
                },
                "example": {
                  "id": "c0a80101-7777-4777-8777-777777777777",
                  "name": "Recuperação de orçamento",
                  "status": "active",
                  "trigger": {
                    "webhook_enabled": true,
                    "type": "webhook",
                    "tag_id": null,
                    "stage_id": null
                  },
                  "node_count": 6
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um fluxo, com o gatilho, as condições de saída e quantos passos ele tem.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/automations/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/automations/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/automations/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/automations/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/automations/{id}/runs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Automações"
        ],
        "summary": "Execuções do fluxo",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por situação da execução."
          },
          {
            "name": "contact_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Execuções de um contato específico."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de execuções",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRunList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                      "flow_id": "c0a80101-7777-4777-8777-777777777777",
                      "contact_id": "c0a80101-1111-4111-8111-111111111111",
                      "phone": "5511987654321",
                      "status": "running",
                      "current_node_id": "node_espera_2",
                      "next_action_at": "2026-09-09T09:00:00Z",
                      "exit_reason": null,
                      "trigger_source": "api",
                      "metadata": {},
                      "started_at": "2026-09-08T09:00:00Z",
                      "ended_at": null
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As passagens de contatos por este fluxo, da mais recente para a mais\nantiga. Mostra em que passo cada um está e por que os que saíram saíram.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/automations/{id}/runs\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/automations/{id}/runs\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/automations/{id}/runs\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/automations/{id}/runs\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/automations/{id}/start": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Automações"
        ],
        "summary": "Coloca um contato no fluxo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone"
                ],
                "properties": {
                  "phone": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "custom_fields": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "name": "Marina Alves",
                "custom_fields": {
                  "orcamento": "1890"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Execução criada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRun"
                },
                "example": {
                  "id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                  "flow_id": "c0a80101-7777-4777-8777-777777777777",
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "phone": "5511987654321",
                  "status": "running",
                  "started_at": "2026-09-08T12:50:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "description": "Contato em opt-out"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Já está no fluxo, ou em período de espera"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Coloca um contato no fluxo. O contato é criado ou atualizado na mesma\nchamada, então você não precisa cadastrar antes.\n\nO fluxo precisa estar ativo. Se o contato já estiver nele, ou tiver saído\nhá menos tempo que o período de espera configurado, a resposta é `409`.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/automations/{id}/start\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"name\": \"Marina Alves\",\n    \"custom_fields\": {\n      \"orcamento\": \"1890\"\n    }\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/automations/{id}/start\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"name\": \"Marina Alves\",\n    \"custom_fields\": {\n      \"orcamento\": \"1890\"\n    }\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/automations/{id}/start\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"name\": \"Marina Alves\",\n        \"custom_fields\": {\n            \"orcamento\": \"1890\"\n        }\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/automations/{id}/start\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"name\":\"Marina Alves\",\"custom_fields\":{\"orcamento\":\"1890\"}}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/automations/{id}/stop": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Automações"
        ],
        "summary": "Tira um contato do fluxo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone": {
                    "type": "string"
                  },
                  "contact_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "phone": "+5511987654321",
                "reason": "Cliente respondeu por telefone"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Execução encerrada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationRun"
                },
                "example": {
                  "id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                  "status": "stopped",
                  "exit_reason": "Cliente respondeu por telefone",
                  "ended_at": "2026-09-08T12:52:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Tira o contato do fluxo antes da hora. Serve para parar a sequência quando ele já resolveu o assunto por outro canal.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/automations/{id}/stop\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"+5511987654321\",\n    \"reason\": \"Cliente respondeu por telefone\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/automations/{id}/stop\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"phone\": \"+5511987654321\",\n    \"reason\": \"Cliente respondeu por telefone\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/automations/{id}/stop\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"phone\": \"+5511987654321\",\n        \"reason\": \"Cliente respondeu por telefone\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/automations/{id}/stop\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"phone\":\"+5511987654321\",\"reason\":\"Cliente respondeu por telefone\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/automation-trigger": {
      "post": {
        "tags": [
          "Automações"
        ],
        "summary": "Dispara um fluxo por token",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone"
                ],
                "properties": {
                  "phone": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "custom_fields": {
                    "type": "object"
                  }
                }
              },
              "example": {
                "token": "fluxo_token_exemplo",
                "phone": "+5511987654321",
                "name": "Marina Alves"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Execução criada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "run_id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                  "contact_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Dispara um fluxo usando o token do próprio fluxo, sem chave de API. É o\nformato antigo, mantido para as integrações que já existem.\n\nEm código novo, prefira `POST /automations/{id}/start`, que usa a chave\n`wevi_` como todo o resto e devolve o erro no envelope padrão.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/automation-trigger\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"token\": \"fluxo_token_exemplo\",\n    \"phone\": \"+5511987654321\",\n    \"name\": \"Marina Alves\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/automation-trigger\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"token\": \"fluxo_token_exemplo\",\n    \"phone\": \"+5511987654321\",\n    \"name\": \"Marina Alves\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/automation-trigger\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"token\": \"fluxo_token_exemplo\",\n        \"phone\": \"+5511987654321\",\n        \"name\": \"Marina Alves\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/automation-trigger\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"token\":\"fluxo_token_exemplo\",\"phone\":\"+5511987654321\",\"name\":\"Marina Alves\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Lista os webhooks cadastrados",
        "responses": {
          "200": {
            "description": "Lista de webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-8888-4888-8888-888888888888",
                      "url": "https://sistema.clinicabemestar.com.br/wevichat",
                      "description": "CRM",
                      "events": [
                        "message.received",
                        "conversation.handoff_requested"
                      ],
                      "active": true,
                      "health": {
                        "failure_count": 0,
                        "failing_since": null,
                        "last_success_at": "2026-09-08T12:00:00Z",
                        "disabled_at": null,
                        "disabled_reason": null
                      },
                      "created_at": "2026-08-01T10:00:00Z",
                      "updated_at": "2026-08-01T10:00:00Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os endereços cadastrados para receber eventos, com a saúde de cada um. O\nsegredo de assinatura não aparece aqui: ele só é mostrado uma vez, na\ncriação.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/webhooks\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/webhooks\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Cadastra um webhook",
        "description": "Cadastra um endereço para receber eventos. A resposta traz o `secret`, que\naparece uma vez só: guarde agora, porque não há como consultá-lo depois,\nsó gerar outro.\n\nConfira a assinatura de cada entrega com esse segredo. Sem isso, quem\ndescobrir o seu endereço consegue inventar um evento.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              },
              "example": {
                "url": "https://sistema.clinicabemestar.com.br/wevichat",
                "events": [
                  "message.received",
                  "conversation.handoff_requested"
                ],
                "description": "CRM"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook criado, com o segredo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                },
                "example": {
                  "id": "c0a80101-8888-4888-8888-888888888888",
                  "url": "https://sistema.clinicabemestar.com.br/wevichat",
                  "description": "CRM",
                  "events": [
                    "message.received",
                    "conversation.handoff_requested"
                  ],
                  "active": true,
                  "secret": "whsec_3f9a1c7e5b2d4088a1f6c3e9d7b5a2c4",
                  "health": {
                    "failure_count": 0,
                    "failing_since": null,
                    "last_success_at": null,
                    "disabled_at": null,
                    "disabled_reason": null
                  },
                  "created_at": "2026-09-08T12:55:00Z",
                  "updated_at": "2026-09-08T12:55:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/webhooks\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"https://sistema.clinicabemestar.com.br/wevichat\",\n    \"events\": [\n      \"message.received\",\n      \"conversation.handoff_requested\"\n    ],\n    \"description\": \"CRM\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"url\": \"https://sistema.clinicabemestar.com.br/wevichat\",\n    \"events\": [\n      \"message.received\",\n      \"conversation.handoff_requested\"\n    ],\n    \"description\": \"CRM\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/webhooks\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"url\": \"https://sistema.clinicabemestar.com.br/wevichat\",\n        \"events\": [\n            \"message.received\",\n            \"conversation.handoff_requested\"\n        ],\n        \"description\": \"CRM\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"url\":\"https://sistema.clinicabemestar.com.br/wevichat\",\"events\":[\"message.received\",\"conversation.handoff_requested\"],\"description\":\"CRM\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks/event-types": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Todos os tipos de evento disponíveis",
        "responses": {
          "200": {
            "description": "Lista de tipos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventTypeList"
                },
                "example": {
                  "data": [
                    "message.received",
                    "message.sent",
                    "message.delivered",
                    "conversation.handoff_requested",
                    "contact.stage_changed"
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Todos os tipos de evento que dá para assinar, como uma lista de\nidentificadores. Use para validar do seu lado antes de mandar em\n`POST /webhooks`, em vez de descobrir pelo `400`.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/webhooks/event-types\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/event-types\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/webhooks/event-types\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/event-types\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Um webhook",
        "responses": {
          "200": {
            "description": "Webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "example": {
                  "id": "c0a80101-8888-4888-8888-888888888888",
                  "url": "https://sistema.clinicabemestar.com.br/wevichat",
                  "events": [
                    "message.received"
                  ],
                  "active": true,
                  "health": {
                    "failure_count": 0,
                    "failing_since": null,
                    "last_success_at": "2026-09-08T12:00:00Z",
                    "disabled_at": null,
                    "disabled_reason": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um webhook, com a saúde da entrega. O segredo não vem junto.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/webhooks/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Altera url, eventos, descrição ou situação",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "description": {
                    "type": "string"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "events": [
                  "message.received",
                  "message.failed"
                ],
                "active": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook atualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "example": {
                  "id": "c0a80101-8888-4888-8888-888888888888",
                  "url": "https://sistema.clinicabemestar.com.br/wevichat",
                  "events": [
                    "message.received",
                    "message.failed"
                  ],
                  "active": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Muda endereço, eventos assinados, descrição ou liga e desliga o webhook.\nDesligar com `active: false` para a entrega sem apagar o histórico.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X PATCH \"https://api.wevi.chat/functions/v1/webhooks/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"events\": [\n      \"message.received\",\n      \"message.failed\"\n    ],\n    \"active\": true\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}\", {\n  method: \"PATCH\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"events\": [\n      \"message.received\",\n      \"message.failed\"\n    ],\n    \"active\": true\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.patch(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"events\": [\n            \"message.received\",\n            \"message.failed\"\n        ],\n        \"active\": True\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"PATCH\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"events\":[\"message.received\",\"message.failed\"],\"active\":true}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Remove o webhook e o histórico dele",
        "responses": {
          "200": {
            "description": "Webhook removido",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "deleted": true,
                  "id": "c0a80101-8888-4888-8888-888888888888"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Remove o webhook e o histórico de entregas dele. Não tem volta.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X DELETE \"https://api.wevi.chat/functions/v1/webhooks/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}\", {\n  method: \"DELETE\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.delete(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"DELETE\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks/{id}/test": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Dispara um evento de teste",
        "responses": {
          "200": {
            "description": "Evento enfileirado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "event_id": "c0a80101-9a9a-4a9a-8a9a-9a9a9a9a9a9a",
                  "delivery_id": "c0a80101-9b9b-4b9b-8b9b-9b9b9b9b9b9b",
                  "message": "Evento de teste enfileirado. Veja o resultado em GET /webhooks/{id}/deliveries."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Enfileira um evento de teste para o endereço. Serve para conferir, antes\nde depender disso, que o seu servidor recebe e que a sua verificação de\nassinatura passa.\n\nO resultado aparece em `GET /webhooks/{id}/deliveries` alguns segundos\ndepois.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/webhooks/{id}/test\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}/test\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}/test\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}/test\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Gera um segredo novo",
        "responses": {
          "200": {
            "description": "Segredo novo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                },
                "example": {
                  "id": "c0a80101-8888-4888-8888-888888888888",
                  "url": "https://sistema.clinicabemestar.com.br/wevichat",
                  "secret": "whsec_8d2b6f4a9c1e5073b8a4f2d6c9e1b3a5",
                  "active": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Gera um segredo novo e invalida o antigo na hora. A resposta mostra o novo\numa vez só.\n\nTroque as duas pontas junto: entre a rotação aqui e a atualização no seu\nservidor, as entregas chegam assinadas com o segredo novo e a sua\nverificação com o antigo vai recusar.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/webhooks/{id}/rotate-secret\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}/rotate-secret\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}/rotate-secret\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}/rotate-secret\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks/{id}/deliveries": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Tentativas de entrega",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivering",
                "succeeded",
                "failed",
                "exhausted"
              ]
            },
            "description": "Filtra por situação da entrega."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de entregas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-9b9b-4b9b-8b9b-9b9b9b9b9b9b",
                      "event_id": "c0a80101-9a9a-4a9a-8a9a-9a9a9a9a9a9a",
                      "endpoint_id": "c0a80101-8888-4888-8888-888888888888",
                      "event_type": "message.received",
                      "status": "succeeded",
                      "attempt": 1,
                      "next_attempt_at": null,
                      "response_status": 200,
                      "response_body": "{\"ok\":true}",
                      "error": null,
                      "duration_ms": 159,
                      "delivered_at": "2026-09-08T12:56:10Z",
                      "created_at": "2026-09-08T12:56:09Z"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "As tentativas de entrega, da mais recente para a mais antiga, com o HTTP\nque o seu servidor devolveu e os primeiros bytes da resposta. É o primeiro\nlugar a olhar quando um evento não chegou.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/webhooks/{id}/deliveries/{delivery_id}/retry": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        },
        {
          "name": "delivery_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Reenvia uma entrega",
        "responses": {
          "200": {
            "description": "Reenvio na fila",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Ok"
                },
                "example": {
                  "ok": true,
                  "delivery_id": "c0a80101-9b9b-4b9b-8b9b-9b9b9b9b9b9b",
                  "status": "pending"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Reenvia uma entrega que falhou, sem esperar a próxima retentativa automática. Use depois de corrigir o seu lado.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries/{delivery_id}/retry\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries/{delivery_id}/retry\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries/{delivery_id}/retry\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/webhooks/{id}/deliveries/{delivery_id}/retry\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/events": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Os mesmos eventos do webhook, por consulta",
        "description": "Os mesmos eventos do webhook, por consulta. Serve para quem não tem\nendereço público: um script atrás de firewall, ou um n8n em rede fechada.\n\nGuarde o `created_at` do último evento que você processou e mande em\n`since` na chamada seguinte. Os eventos ficam disponíveis por 7 dias.\n",
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Traz só os eventos criados depois desta data."
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtra por tipo de evento."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de eventos",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventList"
                },
                "example": {
                  "data": [
                    {
                      "id": "evt_9d1b6631d791441ab347dfee019a2187",
                      "type": "contact.stage_changed",
                      "api_version": "v1",
                      "created_at": "2026-09-08T12:58:00Z",
                      "org_id": "c0a80101-0000-4000-8000-000000000000",
                      "data": {
                        "object": {
                          "id": "c0a80101-1111-4111-8111-111111111111",
                          "name": "Marina Alves",
                          "phone": "5511987654321"
                        },
                        "pipeline": "Funil de vendas",
                        "from": "Contato",
                        "to": "Proposta enviada"
                      }
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/events\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/events\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/events\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/events\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/partner/clients": {
      "get": {
        "tags": [
          "Parceiros"
        ],
        "summary": "Lista os clientes do parceiro",
        "parameters": [
          {
            "name": "plan",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "basico",
                "pro",
                "ultra"
              ]
            },
            "description": "Filtra por plano contratado."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Busca pelo nome do cliente."
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Lista de clientes, com o consumo do mês de cada um",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerClientList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c0a80101-c1c1-4c1c-8c1c-c1c1c1c1c1c1",
                      "name": "Clínica Bem Estar",
                      "slug": "clinica-bem-estar",
                      "plan": "pro",
                      "plan_started_at": "2026-07-01T10:00:00Z",
                      "trial_ends_at": null,
                      "primary_color": "#B5F03F",
                      "logo_url": null,
                      "custom_domain": null,
                      "created_at": "2026-07-01T10:00:00Z",
                      "usage": {
                        "period_start": "2026-09-01T00:00:00Z",
                        "conversations_this_month": 412,
                        "agents": 2,
                        "members": 3
                      }
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os clientes desta organização parceira, com o consumo do mês de cada um.\n\nServe para o parceiro montar o próprio painel de clientes, sem espelhar\ndados nossos no banco dele.\n\nOrganização que não é parceira recebe `403 not_a_partner`.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/partner/clients\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/partner/clients\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/partner/clients\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/partner/clients\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "post": {
        "tags": [
          "Parceiros"
        ],
        "summary": "Cria um cliente",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerClientCreate"
              },
              "example": {
                "name": "Clínica Bem Estar",
                "plan": "pro",
                "primary_color": "#B5F03F"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cliente criado, com o link do convite",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerClientCreated"
                },
                "example": {
                  "id": "c0a80101-c1c1-4c1c-8c1c-c1c1c1c1c1c1",
                  "name": "Clínica Bem Estar",
                  "slug": "clinica-bem-estar",
                  "plan": "pro",
                  "plan_started_at": "2026-09-08T16:00:00Z",
                  "trial_ends_at": null,
                  "primary_color": "#B5F03F",
                  "logo_url": null,
                  "custom_domain": null,
                  "created_at": "2026-09-08T16:00:00Z",
                  "invite_url": "https://app.wevi.chat/convite/b6946eee0b4c4330ba86041d46d11a86"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Cria o espaço de um cliente dentro da sua organização parceira.\n\nSem `plan`, ele nasce em teste de 15 dias. Com `plan`, nasce ativo e entra\nna sua cobrança na hora, o que exige a sua assinatura de parceiro ativa.\n\nA resposta traz `invite_url`. Mande esse link para o cliente: é por ele que\nalguém do lado dele assume o espaço como administrador. Sem isso, o espaço\nexiste mas não tem dono humano.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/partner/clients\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Clínica Bem Estar\",\n    \"plan\": \"pro\",\n    \"primary_color\": \"#B5F03F\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/partner/clients\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Clínica Bem Estar\",\n    \"plan\": \"pro\",\n    \"primary_color\": \"#B5F03F\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/partner/clients\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"name\": \"Clínica Bem Estar\",\n        \"plan\": \"pro\",\n        \"primary_color\": \"#B5F03F\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/partner/clients\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"name\":\"Clínica Bem Estar\",\"plan\":\"pro\",\"primary_color\":\"#B5F03F\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/partner/clients/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "get": {
        "tags": [
          "Parceiros"
        ],
        "summary": "Um cliente, com o consumo do mês",
        "responses": {
          "200": {
            "description": "O cliente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerClient"
                },
                "example": {
                  "id": "c0a80101-c1c1-4c1c-8c1c-c1c1c1c1c1c1",
                  "name": "Clínica Bem Estar",
                  "slug": "clinica-bem-estar",
                  "plan": "pro",
                  "plan_started_at": "2026-07-01T10:00:00Z",
                  "trial_ends_at": null,
                  "primary_color": "#B5F03F",
                  "logo_url": null,
                  "custom_domain": null,
                  "created_at": "2026-07-01T10:00:00Z",
                  "usage": {
                    "period_start": "2026-09-01T00:00:00Z",
                    "conversations_this_month": 412,
                    "agents": 2,
                    "members": 3
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Um cliente seu, com o consumo do mês. Cliente de outro parceiro responde\n`404`, não `403`: para a sua chave, ele não existe.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/partner/clients/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/partner/clients/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/partner/clients/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/partner/clients/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      },
      "patch": {
        "tags": [
          "Parceiros"
        ],
        "summary": "Altera nome e identidade visual",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerClientUpdate"
              },
              "example": {
                "primary_color": "#1CB945",
                "logo_url": "https://cdn.exemplo.com/logo.png"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "O cliente atualizado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerClient"
                },
                "example": {
                  "id": "c0a80101-c1c1-4c1c-8c1c-c1c1c1c1c1c1",
                  "name": "Clínica Bem Estar",
                  "slug": "clinica-bem-estar",
                  "plan": "pro",
                  "plan_started_at": "2026-07-01T10:00:00Z",
                  "trial_ends_at": null,
                  "primary_color": "#1CB945",
                  "logo_url": "https://cdn.exemplo.com/logo.png",
                  "custom_domain": null,
                  "created_at": "2026-07-01T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Altera nome, cor, logotipo e domínio próprio do cliente.\n\nTrocar de plano ainda passa pelo painel, porque mexe na sua cobrança no\nStripe. Mandar `plan` aqui devolve `409` explicando isso.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X PATCH \"https://api.wevi.chat/functions/v1/partner/clients/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"primary_color\": \"#1CB945\",\n    \"logo_url\": \"https://cdn.exemplo.com/logo.png\"\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/partner/clients/{id}\", {\n  method: \"PATCH\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"primary_color\": \"#1CB945\",\n    \"logo_url\": \"https://cdn.exemplo.com/logo.png\"\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.patch(\n    \"https://api.wevi.chat/functions/v1/partner/clients/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"primary_color\": \"#1CB945\",\n        \"logo_url\": \"https://cdn.exemplo.com/logo.png\"\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/partner/clients/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"PATCH\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"primary_color\":\"#1CB945\",\"logo_url\":\"https://cdn.exemplo.com/logo.png\"}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/partner/clients/{id}/keys": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathId"
        }
      ],
      "post": {
        "tags": [
          "Parceiros"
        ],
        "summary": "Gera uma chave dentro do cliente",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerKeyCreate"
              },
              "example": {
                "name": "integração do parceiro",
                "scopes": [
                  "contacts:read",
                  "messages:send"
                ],
                "is_test": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "A chave criada. O token aparece uma vez só",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerKeyCreated"
                },
                "example": {
                  "id": "c0a80101-d1d1-4d1d-8d1d-d1d1d1d1d1d1",
                  "org_id": "c0a80101-c1c1-4c1c-8c1c-c1c1c1c1c1c1",
                  "name": "integração do parceiro",
                  "token": "wevi_test_b9f3c2a15e8d47069b1a3f6c8e2d5074a9c1b3e6f8027d4a5b9c1e3f7a2d6094",
                  "token_prefix": "wevi_test_b9",
                  "scopes": [
                    "contacts:read",
                    "messages:send"
                  ],
                  "expires_at": null,
                  "is_test": true,
                  "created_at": "2026-09-08T16:05:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Gera uma chave de API dentro do espaço do cliente, para o seu sistema\noperar aquele espaço.\n\nA chave vale só naquele cliente: ela não enxerga os seus outros clientes\nnem a sua organização parceira. O token aparece uma vez só, nesta resposta.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X POST \"https://api.wevi.chat/functions/v1/partner/clients/{id}/keys\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"integração do parceiro\",\n    \"scopes\": [\n      \"contacts:read\",\n      \"messages:send\"\n    ],\n    \"is_test\": true\n  }'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/partner/clients/{id}/keys\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"integração do parceiro\",\n    \"scopes\": [\n      \"contacts:read\",\n      \"messages:send\"\n    ],\n    \"is_test\": true\n  }),\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.post(\n    \"https://api.wevi.chat/functions/v1/partner/clients/{id}/keys\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n    json={\n        \"name\": \"integração do parceiro\",\n        \"scopes\": [\n            \"contacts:read\",\n            \"messages:send\"\n        ],\n        \"is_test\": True\n    },\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/partner/clients/{id}/keys\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"POST\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n    CURLOPT_POSTFIELDS => json_encode({\"name\":\"integração do parceiro\",\"scopes\":[\"contacts:read\",\"messages:send\"],\"is_test\":true}),\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/partner/usage": {
      "get": {
        "tags": [
          "Parceiros"
        ],
        "summary": "Consumo de todos os clientes",
        "responses": {
          "200": {
            "description": "Consumo agregado e por cliente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerUsage"
                },
                "example": {
                  "clients": 2,
                  "by_plan": {
                    "pro": 1,
                    "basico": 1
                  },
                  "conversations_this_month": 588,
                  "data": [
                    {
                      "client_id": "c0a80101-c1c1-4c1c-8c1c-c1c1c1c1c1c1",
                      "name": "Clínica Bem Estar",
                      "plan": "pro",
                      "period_start": "2026-09-01T00:00:00Z",
                      "conversations_this_month": 412,
                      "agents": 2,
                      "members": 3
                    },
                    {
                      "client_id": "c0a80101-c2c2-4c2c-8c2c-c2c2c2c2c2c2",
                      "name": "Estúdio Norte",
                      "plan": "basico",
                      "period_start": "2026-09-01T00:00:00Z",
                      "conversations_this_month": 176,
                      "agents": 1,
                      "members": 2
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "O consumo de todos os seus clientes de uma vez, agregado e por cliente.\nÉ o número que fecha com a sua fatura de licenças no fim do mês.\n\nOrganização que não é parceira recebe `403 not_a_partner`.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/partner/usage\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/partner/usage\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/partner/usage\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/partner/usage\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/org": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "A organização da chave",
        "description": "A organização da chave, com o plano, os limites e o consumo do mês. Limite\nsem teto vem como `null`, porque JSON não tem infinito.\n\nConsulte antes de uma carga grande para saber quanto ainda cabe.\n\nO campo `alerts` traz o que está quebrado agora: webhook falhando há mais\nde uma hora, número de WhatsApp com erro de configuração, chave prestes a\nvencer. Vem vazio quando está tudo certo.\n",
        "responses": {
          "200": {
            "description": "Organização",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Org"
                },
                "example": {
                  "id": "c0a80101-0000-4000-8000-000000000000",
                  "name": "Clínica Bem Estar",
                  "slug": "clinica-bem-estar",
                  "type": "client",
                  "is_partner": false,
                  "custom_domain": null,
                  "created_at": "2026-06-01T09:00:00Z",
                  "plan": {
                    "tier": "pro",
                    "trial_ends_at": null,
                    "limits": {
                      "agents": 5,
                      "conversations_per_month": null,
                      "rag_files": null,
                      "members": 5,
                      "campaign_sends_per_month": 5000,
                      "whatsapp": true,
                      "campaigns": true,
                      "api_write": true,
                      "multi_agent": true
                    }
                  },
                  "usage": {
                    "period_start": "2026-09-01T00:00:00Z",
                    "conversations_this_month": 412,
                    "campaign_sends_this_month": 320,
                    "agents": 2,
                    "rag_files": 8,
                    "members": 3
                  },
                  "alerts": [
                    {
                      "type": "webhook_failing",
                      "severity": "warning",
                      "message": "O webhook https://sistema.clinicabemestar.com.br/wevichat está falhando há mais de uma hora.",
                      "resource_id": "c0a80101-8888-4888-8888-888888888888",
                      "since": "2026-09-08T11:40:00Z",
                      "detail": {
                        "url": "https://sistema.clinicabemestar.com.br/wevichat",
                        "failure_count": 14,
                        "disabled_at": null,
                        "disabled_reason": null
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/org\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/org\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/org\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/org\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/org/usage": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Consumo do mês corrente",
        "responses": {
          "200": {
            "description": "Consumo",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                },
                "example": {
                  "period_start": "2026-09-01T00:00:00Z",
                  "conversations_this_month": 412,
                  "campaign_sends_this_month": 320,
                  "agents": 2,
                  "rag_files": 8,
                  "members": 3
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Só o consumo do mês, sem os dados da organização. Mais barato para um painel que atualiza sozinho.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/org/usage\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/org/usage\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/org/usage\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/org/usage\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/analytics/overview": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Números do atendimento",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Início do período, em ISO 8601. Padrão: 30 dias atrás."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fim do período, em ISO 8601. Padrão: agora."
          }
        ],
        "responses": {
          "200": {
            "description": "Métricas do período",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Analytics"
                },
                "example": {
                  "period": {
                    "from": "2026-08-09T00:00:00Z",
                    "to": "2026-09-08T00:00:00Z"
                  },
                  "conversations": {
                    "total": 258,
                    "resolved": 190,
                    "open": 68,
                    "by_channel": {
                      "whatsapp": 185,
                      "web": 72,
                      "api": 1
                    },
                    "from_ads": 53
                  },
                  "messages": {
                    "inbound": 401,
                    "outbound": 478,
                    "total": 879
                  },
                  "handoff": {
                    "requested": 25,
                    "taken_over": 22,
                    "rate": 0.097
                  },
                  "ratings": {
                    "count": 131,
                    "average": 4.85
                  },
                  "sentiment": {
                    "positive": 168,
                    "neutral": 74,
                    "negative": 16
                  },
                  "conversion_events": {
                    "agendamento_marcado": 41
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os números do atendimento no período: conversas, mensagens, transbordos,\navaliações e humor. Sem `from` e `to`, usa os últimos 30 dias.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/analytics/overview\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/analytics/overview\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/analytics/overview\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/analytics/overview\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/analytics/agents/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PathIdOrSlug"
        }
      ],
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Os mesmos números, para um agente",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Início do período, em ISO 8601. Padrão: 30 dias atrás."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Fim do período, em ISO 8601. Padrão: agora."
          }
        ],
        "responses": {
          "200": {
            "description": "Métricas do agente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Analytics"
                },
                "example": {
                  "period": {
                    "from": "2026-08-09T00:00:00Z",
                    "to": "2026-09-08T00:00:00Z"
                  },
                  "conversations": {
                    "total": 185,
                    "resolved": 140,
                    "open": 45,
                    "by_channel": {
                      "whatsapp": 185
                    },
                    "from_ads": 53
                  },
                  "messages": {
                    "inbound": 300,
                    "outbound": 355,
                    "total": 655
                  },
                  "handoff": {
                    "requested": 18,
                    "taken_over": 16,
                    "rate": 0.097
                  },
                  "ratings": {
                    "count": 98,
                    "average": 4.9
                  },
                  "sentiment": {
                    "positive": 130,
                    "neutral": 45,
                    "negative": 10
                  },
                  "conversion_events": {
                    "agendamento_marcado": 33
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Os mesmos números, só do que passou por um agente. Serve para comparar dois agentes no mesmo período.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/analytics/agents/{id}\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/analytics/agents/{id}\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/analytics/agents/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/analytics/agents/{id}\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/health": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Ping para monitoramento",
        "security": [],
        "responses": {
          "200": {
            "description": "Serviço no ar",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "example": {
                  "status": "ok",
                  "ts": "2026-09-08T13:00:00Z",
                  "db_ms": 233
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Responde sem autenticação, para você apontar o seu monitoramento. Além do\nstatus, devolve `db_ms`, o tempo de uma consulta trivial ao banco: é o que\nsepara \"a API está de pé\" de \"a API está rápida\".\n\nSe o banco não responder, o status vira `degraded` e o HTTP, `503`.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/health\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/health\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/health\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/health\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    },
    "/openapi": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Esta especificação",
        "security": [],
        "responses": {
          "200": {
            "description": "Especificação OpenAPI",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenApiDocument"
                },
                "example": {
                  "openapi": "3.1.0",
                  "info": {
                    "title": "API Wevichat",
                    "version": "1.0.0"
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "description": "Esta especificação, em JSON, sem autenticação. Aponte a sua ferramenta\npara cá e ela gera o cliente sozinha.\n",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "curl",
            "source": "curl -X GET \"https://api.wevi.chat/functions/v1/openapi\" \\\n  -H \"Authorization: Bearer wevi_SUA_CHAVE\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const res = await fetch(\"https://api.wevi.chat/functions/v1/openapi\", {\n  method: \"GET\",\n  headers: {\n    Authorization: `Bearer ${process.env.WEVI_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n});\n\nif (!res.ok) {\n  const erro = await res.json();\n  throw new Error(`${erro.error}: ${erro.message} (${erro.request_id})`);\n}\nconst dados = await res.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os, requests\n\nres = requests.get(\n    \"https://api.wevi.chat/functions/v1/openapi\",\n    headers={\"Authorization\": f\"Bearer {os.environ['WEVI_API_KEY']}\"},\n)\n\nres.raise_for_status()\ndados = res.json()"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.wevi.chat/functions/v1/openapi\");\ncurl_setopt_array($ch, [\n    CURLOPT_RETURNTRANSFER => true,\n    CURLOPT_CUSTOMREQUEST => \"GET\",\n    CURLOPT_HTTPHEADER => [\n        \"Authorization: Bearer \" . getenv(\"WEVI_API_KEY\"),\n        \"Content-Type: application/json\",\n    ],\n]);\n\n$dados = json_decode(curl_exec($ch), true);"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Chave criada em Conta > Desenvolvedores. Formato `wevi_` seguido de 64\ncaracteres. Chaves `wevi_test_` rodam em modo de teste: nada sai para o\nWhatsApp de verdade.\n"
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Itens por página. Máximo 200.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "O `next_cursor` da página anterior.",
        "schema": {
          "type": "string"
        }
      },
      "UpdatedSince": {
        "name": "updated_since",
        "in": "query",
        "description": "Devolve só o que mudou depois desta data.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "PathId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "PathIdOrSlug": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "UUID ou slug público.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Chave ausente, inválida, revogada ou expirada",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Corpo inválido ou campo obrigatório faltando",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Recurso não existe nesta organização",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PlanLimit": {
        "description": "O plano não inclui este recurso, ou o limite do mês acabou",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Autenticado, mas a ação não é permitida neste estado",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "O recurso está num estado que não aceita esta ação",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InternalError": {
        "description": "Erro do nosso lado. Guarde o request_id e tente de novo",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "A API está de pé mas alguma dependência não respondeu",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Health"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "O corpo faz sentido, mas o conteúdo não pode ser aceito",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Limite de requisições por minuto atingido",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Segundos até poder tentar de novo"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "O corpo de toda resposta de erro, em qualquer endpoint. O `error` é um\ncódigo estável para o seu código ramificar; o `message` é para humanos\ne pode mudar entre versões.\n",
        "properties": {
          "error": {
            "type": "string",
            "description": "Código estável, em snake_case.",
            "examples": [
              "missing_connection_id"
            ]
          },
          "message": {
            "type": "string",
            "description": "Explicação para humanos, em português.",
            "examples": [
              "connection_id is required"
            ]
          },
          "details": {
            "type": "object",
            "description": "Campos extras do erro, quando existem. Varia por código.",
            "examples": [
              {
                "unknown_fields": [
                  "texto"
                ],
                "allowed_fields": [
                  "to",
                  "connection_id",
                  "text"
                ]
              }
            ]
          },
          "request_id": {
            "type": "string",
            "description": "O mesmo valor do header `X-Request-Id`. Mande no chamado.",
            "examples": [
              "req_3c119400bd87452483cc18eeea44b181"
            ]
          },
          "docs_url": {
            "type": "string",
            "format": "uri",
            "description": "Link direto para este código no catálogo de erros."
          }
        },
        "required": [
          "error",
          "message",
          "request_id"
        ]
      },
      "ListEnvelope": {
        "type": "object",
        "description": "O formato de toda lista. A paginação é por cursor: mande o\n`next_cursor` da página anterior em `?cursor=` para continuar.\n",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Os itens desta página."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor da próxima página. `null` quando acabou."
          },
          "has_more": {
            "type": "boolean",
            "description": "Se existe página seguinte."
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "Ok": {
        "type": "object",
        "description": "Confirmação simples, para ações que não devolvem recurso.",
        "properties": {
          "ok": {
            "type": "boolean",
            "examples": [
              true
            ]
          }
        },
        "required": [
          "ok"
        ]
      },
      "Contact": {
        "type": "object",
        "description": "Uma pessoa que fala com você, com tudo que sabemos dela.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nome de exibição."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sempre em E.164 sem o `+`, o mesmo formato que o WhatsApp usa.",
            "examples": [
              "5548988060000"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Anotação livre do cadastro."
          },
          "custom_fields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Campos personalizados da organização. As chaves precisam existir em Campos personalizados."
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "pipelines": {
            "type": "array",
            "description": "A posição do contato em cada funil.",
            "items": {
              "$ref": "#/components/schemas/ContactPipelinePosition"
            }
          },
          "assigned_user": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/User"
              },
              {
                "type": "null"
              }
            ],
            "description": "Dono da carteira."
          },
          "identifiers": {
            "type": "array",
            "description": "Todos os telefones e emails conhecidos do contato.",
            "items": {
              "$ref": "#/components/schemas/ContactIdentifier"
            }
          },
          "stats": {
            "$ref": "#/components/schemas/ContactStats"
          },
          "opted_out_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Quando pediu para não receber mais. `null` significa que aceita."
          },
          "assigned_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "assignment_source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Como ganhou dono: manual, automação ou rodízio."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id"
        ]
      },
      "ContactIdentifier": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "phone",
              "email",
              "cpf"
            ]
          },
          "value": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rótulo livre: pessoal, comercial."
          }
        }
      },
      "ContactPipelinePosition": {
        "type": "object",
        "properties": {
          "pipeline_id": {
            "type": "string",
            "format": "uuid"
          },
          "pipeline_name": {
            "type": "string"
          },
          "stage_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "stage_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "entered_stage_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lost_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Preenchido quando o contato foi marcado como perdido."
          },
          "lost_reason": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ContactStats": {
        "type": "object",
        "description": "Números do relacionamento, calculados na hora da leitura.",
        "properties": {
          "conversation_count": {
            "type": "integer"
          },
          "first_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Canais por onde já falou."
          }
        }
      },
      "ContactList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          }
        ]
      },
      "ContactUpsert": {
        "type": "object",
        "description": "Informe ao menos `email` ou `phone`. Existindo, atualiza; senão, cria.",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string",
            "description": "Qualquer formato é aceito na entrada e normalizado na gravação.",
            "examples": [
              "+55 48 98806-0000"
            ]
          },
          "name": {
            "type": "string"
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Chaves precisam existir em Campos personalizados, senão a resposta é `400 unknown_fields`."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Etiquetas por nome. As que não existirem são criadas."
          },
          "assigned_user_email": {
            "type": "string",
            "format": "email",
            "description": "Email de um membro da organização, para virar dono da carteira. Se\no email não for de um membro, o contato é gravado mesmo assim e a\nresposta traz `assignment_error`.\n"
          }
        },
        "anyOf": [
          {
            "required": [
              "email"
            ]
          },
          {
            "required": [
              "phone"
            ]
          }
        ]
      },
      "ContactUpsertItem": {
        "type": "object",
        "description": "O mesmo corpo do `POST /contacts`. Item sem `email` nem `phone` não\nderruba o lote: ele volta como falha na posição dele, com o motivo.\n",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "assigned_user_email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "ContactUpsertResult": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Contact"
          },
          {
            "type": "object",
            "description": "O contato completo, mais os campos que as integrações antigas já liam.",
            "properties": {
              "ok": {
                "type": "boolean"
              },
              "contact_id": {
                "type": "string",
                "format": "uuid",
                "description": "O mesmo valor de `id`. Mantido por compatibilidade."
              },
              "tags_assigned": {
                "type": "array",
                "description": "Etiquetas aplicadas nesta chamada, com aviso de quais foram criadas agora.",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "created": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "assigned_user_id": {
                "type": "string",
                "format": "uuid"
              },
              "assignment_error": {
                "type": "string",
                "description": "Presente quando o `assigned_user_email` não pôde ser aplicado."
              }
            }
          }
        ]
      },
      "ContactNote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "body": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "ContactHistoryEntry": {
        "type": "object",
        "description": "Uma linha do histórico do contato, em ordem cronológica.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "stage_changed",
              "assigned",
              "unassigned",
              "note"
            ],
            "description": "O que aconteceu."
          },
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "detail": {
            "type": "object",
            "description": "Campos que variam por tipo."
          }
        }
      },
      "Conversation": {
        "type": "object",
        "description": "Um atendimento, do primeiro contato ao encerramento.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "resolved",
              "archived"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "web",
              "embed",
              "whatsapp",
              "api"
            ],
            "description": "`api` é a conversa criada por `POST /agents/{id}/chat`."
          },
          "contact": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Contact"
              },
              {
                "type": "null"
              }
            ]
          },
          "agent": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Agent"
              },
              {
                "type": "null"
              }
            ]
          },
          "connection_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Número de WhatsApp por onde a conversa acontece."
          },
          "user": {
            "type": "object",
            "description": "Quem está do outro lado, como o canal informou.",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "metadata": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "O que o formulário pré-chat coletou."
              }
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "awaiting_reply": {
            "type": "boolean",
            "description": "A última mensagem foi do cliente e ninguém respondeu."
          },
          "bot_paused_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Até quando a IA fica calada nesta conversa."
          },
          "takeover": {
            "type": [
              "object",
              "null"
            ],
            "description": "Quem assumiu o atendimento, se alguém assumiu.",
            "properties": {
              "user_id": {
                "type": "string",
                "format": "uuid"
              },
              "at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "handoff": {
            "type": [
              "object",
              "null"
            ],
            "description": "Pedido de atendente humano ainda aberto.",
            "properties": {
              "requested_at": {
                "type": "string",
                "format": "date-time"
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "resolved": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "at": {
                "type": "string",
                "format": "date-time"
              },
              "by": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              }
            }
          },
          "rating": {
            "type": [
              "object",
              "null"
            ],
            "description": "Avaliação que o cliente deu ao atendimento.",
            "properties": {
              "score": {
                "type": "integer",
                "minimum": 1,
                "maximum": 5
              },
              "comment": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "sentiment": {
            "type": [
              "object",
              "null"
            ],
            "description": "Leitura automática do humor da conversa, quando o agente tem a análise ligada.",
            "properties": {
              "label": {
                "type": "string",
                "enum": [
                  "positive",
                  "neutral",
                  "negative"
                ]
              },
              "score": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "analyzed_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "referral": {
            "type": [
              "object",
              "null"
            ],
            "description": "O anúncio que originou a conversa, quando ela veio de um Click to WhatsApp.",
            "properties": {
              "source_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "source_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "ctwa_clid": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "at": {
                "type": "string",
                "format": "date-time"
              },
              "raw": {
                "type": [
                  "object",
                  "null"
                ]
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_message_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_inbound_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Última mensagem do cliente. Conta a janela de 24 horas."
          },
          "last_assistant_message_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "channel"
        ]
      },
      "ConversationList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Conversation"
                }
              }
            }
          }
        ]
      },
      "ConversationEvent": {
        "type": "object",
        "description": "Um evento de conversão que o agente detectou na conversa.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "examples": [
              "agendamento_marcado"
            ]
          },
          "metadata": {
            "type": "object"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConversationExport": {
        "type": "object",
        "description": "A conversa inteira, para arquivo ou auditoria.",
        "properties": {
          "conversation": {
            "$ref": "#/components/schemas/Conversation"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          },
          "message_count": {
            "type": "integer"
          },
          "exported_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Message": {
        "type": "object",
        "description": "Uma mensagem dentro de uma conversa.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "conversation_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "role": {
            "type": "string",
            "enum": [
              "user",
              "assistant",
              "system"
            ],
            "description": "`user` é o cliente; `assistant` é a IA ou a equipe."
          },
          "content": {
            "type": "string"
          },
          "file": {
            "type": [
              "object",
              "null"
            ],
            "description": "Anexo, quando a mensagem tem um.",
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              },
              "type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "wamid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador da mensagem na Meta."
          },
          "delivery": {
            "type": "object",
            "properties": {
              "status": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "pending",
                  "sent",
                  "delivered",
                  "read",
                  "failed",
                  null
                ]
              },
              "delivered_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "read_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "failed_reason": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "reply_to_message_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "reactions": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "sent_by": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Membro da equipe que enviou, quando não foi a IA."
          },
          "handled_by_agent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Quem originou: api, campaign, automation."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "role"
        ]
      },
      "MessageList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          }
        ]
      },
      "MessageOrSendList": {
        "description": "`GET /messages` devolve dois tipos no mesmo formato de lista: mensagem\nde conversa quando você filtra por `conversation_id`, e disparo avulso\nno resto dos casos. O campo `kind` só existe no disparo.\n",
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/ApiSend"
                    },
                    {
                      "$ref": "#/components/schemas/Message"
                    }
                  ]
                }
              }
            }
          }
        ]
      },
      "ApiSend": {
        "type": "object",
        "description": "Um disparo avulso, feito pela API para um número, fora de uma conversa\nem andamento. `GET /messages` devolve estes e as mensagens de conversa\nno mesmo formato de lista.\n",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "conversation_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "description": "Tipo enviado: text, template, image, interactive_button."
          },
          "to": {
            "type": "string",
            "description": "Telefone do destinatário, em E.164 sem o `+`."
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "connection_id": {
            "type": "string",
            "format": "uuid"
          },
          "template": {
            "type": [
              "object",
              "null"
            ],
            "description": "Preenchido quando o disparo foi de template.",
            "properties": {
              "name": {
                "type": "string"
              },
              "language_code": {
                "type": "string"
              },
              "body_params": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "content": {
            "type": [
              "string",
              "null"
            ]
          },
          "wamid": {
            "type": [
              "string",
              "null"
            ]
          },
          "delivery": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "sent",
                  "delivered",
                  "read",
                  "failed"
                ]
              },
              "sent_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "delivered_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "read_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "failed_reason": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "idempotency_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SendMessage": {
        "type": "object",
        "required": [
          "type"
        ],
        "description": "O corpo de `POST /messages`. O `type` decide quais outros campos valem:\n`text` usa `text`, `template` usa `template_name` e `body_params`,\nmídia usa `media`, e os interativos usam `body` mais o campo do formato.\n",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text",
              "template",
              "image",
              "audio",
              "video",
              "document",
              "buttons",
              "list",
              "cta_url",
              "location_request",
              "product",
              "product_list"
            ]
          },
          "to": {
            "type": "string",
            "description": "Telefone do destinatário. Alternativa: `conversation_id`."
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "description": "Responde dentro de uma conversa que já existe."
          },
          "connection_id": {
            "type": "string",
            "format": "uuid",
            "description": "Só é obrigatório quando a organização tem mais de um número conectado."
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact": {
            "type": "object",
            "description": "Cria ou atualiza o contato junto do envio, sem precisar de uma segunda chamada.",
            "properties": {
              "name": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            }
          },
          "idempotency_key": {
            "type": "string",
            "description": "Preferir o header `Idempotency-Key`. Este campo continua aceito."
          },
          "open_conversation": {
            "type": "string",
            "enum": [
              "always",
              "on_reply"
            ],
            "description": "`always` abre a conversa no inbox junto do disparo; `on_reply` só abre se o cliente responder."
          },
          "text": {
            "type": "string",
            "description": "Obrigatório para `type: text`."
          },
          "template_name": {
            "type": "string"
          },
          "template_id": {
            "type": "string",
            "description": "O Meta ID do template. Alternativa ao nome."
          },
          "language_code": {
            "type": "string",
            "examples": [
              "pt_BR"
            ]
          },
          "body_params": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Valores das variáveis do corpo do template, em ordem."
          },
          "header_image_url": {
            "type": "string",
            "format": "uri"
          },
          "button_params": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Valores das variáveis dos botões do template."
          },
          "media": {
            "type": "object",
            "description": "Para `image`, `audio`, `video` e `document`. Informe `url` ou `base64`.",
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              },
              "base64": {
                "type": "string",
                "description": "Os bytes do arquivo, para quem não quer hospedar antes."
              },
              "mime_type": {
                "type": "string",
                "examples": [
                  "image/png"
                ]
              },
              "name": {
                "type": "string"
              }
            }
          },
          "caption": {
            "type": "string",
            "description": "Legenda da mídia."
          },
          "body": {
            "type": "string",
            "description": "Texto principal dos tipos interativos."
          },
          "footer": {
            "type": "string"
          },
          "header": {
            "type": "object",
            "description": "Cabeçalho do interativo: `{ type: text, text }` ou mídia."
          },
          "buttons": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Para `type: buttons`. Até 3."
          },
          "sections": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Para `list` e `product_list`."
          },
          "button_text": {
            "type": "string",
            "description": "Rótulo do botão que abre a lista. Máximo 20 caracteres."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Para `type: cta_url`."
          },
          "display_text": {
            "type": "string",
            "description": "Rótulo do botão de link. Máximo 20 caracteres."
          },
          "catalog_id": {
            "type": "string",
            "description": "Quando ausente, usa o catálogo configurado na conexão."
          },
          "product_retailer_id": {
            "type": "string"
          }
        }
      },
      "SendResult": {
        "type": "object",
        "description": "O resultado do envio. Recusa da Meta não é erro de requisição: vem com\n`200` e `status: failed`, com o motivo em `error`. Trate os dois casos.\n",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "O registro do envio, para consultar depois em `GET /messages/{id}`."
          },
          "wamid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identificador na Meta. Em modo de teste começa com `wamid.TEST`."
          },
          "status": {
            "type": "string",
            "enum": [
              "sent",
              "failed"
            ]
          },
          "conversation_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "error": {
            "type": "string",
            "description": "Presente quando a Meta recusou."
          }
        },
        "required": [
          "status"
        ]
      },
      "Agent": {
        "type": "object",
        "description": "Um agente de IA configurado na organização.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "draft",
              "inactive"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "ai",
              "flow"
            ],
            "description": "`flow` é o agente de botões, sem custo de IA."
          },
          "public_slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "public_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "model": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "claude-sonnet-4-6"
            ]
          },
          "temperature": {
            "type": [
              "number",
              "null"
            ]
          },
          "max_tokens": {
            "type": [
              "integer",
              "null"
            ]
          },
          "system_prompt": {
            "type": [
              "string",
              "null"
            ]
          },
          "greeting_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "conversion_events": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Eventos que o agente sabe detectar na conversa."
          },
          "auto_tags": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "features": {
            "type": "object",
            "properties": {
              "sentiment": {
                "type": "boolean"
              },
              "handoff": {
                "type": "boolean"
              },
              "business_hours": {
                "type": "boolean"
              },
              "business_hours_mode": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "conversation_timeout_hours": {
            "type": [
              "integer",
              "null"
            ]
          },
          "rag_top_k": {
            "type": [
              "integer",
              "null"
            ]
          },
          "archived_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "type"
        ]
      },
      "AgentList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Agent"
                }
              }
            }
          }
        ]
      },
      "AgentChatRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "maxLength": 8000,
            "description": "O que o usuário disse."
          },
          "external_user_id": {
            "type": "string",
            "description": "O identificador do usuário no seu sistema. Mande o mesmo valor nas\nchamadas seguintes e a conversa continua de onde parou.\n"
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "description": "Alternativa ao `external_user_id`, para continuar uma conversa específica."
          },
          "user": {
            "type": "object",
            "description": "Dados do usuário, para o agente personalizar a resposta e o contato existir aqui.",
            "properties": {
              "name": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "phone": {
                "type": "string"
              },
              "metadata": {
                "type": "object"
              }
            }
          },
          "async": {
            "type": "boolean",
            "description": "Não espera a IA responder: devolve `202` na hora e a resposta chega\npelo webhook `message.sent`. Use quando a sua chamada tem timeout curto.\n"
          }
        }
      },
      "AgentChatResponse": {
        "type": "object",
        "properties": {
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "description": "Guarde para continuar a conversa."
          },
          "conversation_created": {
            "type": "boolean"
          },
          "message": {
            "type": "object",
            "description": "A resposta do agente.",
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "role": {
                "type": "string",
                "enum": [
                  "assistant"
                ]
              },
              "content": {
                "type": "string"
              }
            }
          },
          "handoff": {
            "type": [
              "object",
              "null"
            ],
            "description": "Preenchido quando o agente pediu atendente humano. A partir daí, quem responde é a sua equipe.",
            "properties": {
              "requested_at": {
                "type": "string",
                "format": "date-time"
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      },
      "KnowledgeDocument": {
        "type": "object",
        "description": "Um documento na base de conhecimento de um agente.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "ready",
              "failed"
            ]
          },
          "chunk_count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Connection": {
        "type": "object",
        "description": "Um número de WhatsApp conectado à organização.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "display_name": {
            "type": "string"
          },
          "phone_number": {
            "type": "string"
          },
          "phone_number_id": {
            "type": "string",
            "description": "O identificador do número na Meta."
          },
          "waba_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "verified_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "quality_rating": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "GREEN",
              "YELLOW",
              "RED",
              null
            ],
            "description": "A nota de qualidade que a Meta dá ao número."
          },
          "agent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Agente que atende neste número."
          },
          "connected_via": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "embedded_signup",
              "coexistence",
              null
            ]
          },
          "is_coexistence": {
            "type": "boolean",
            "description": "O número continua funcionando também no aplicativo do WhatsApp Business."
          },
          "catalog_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "config_error": {
            "type": [
              "object",
              "null"
            ],
            "description": "Preenchido quando a Meta recusou alguma operação por configuração do número.",
            "properties": {
              "message": {
                "type": "string"
              },
              "at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "subscribed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConnectionList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Connection"
                }
              }
            }
          }
        ]
      },
      "Template": {
        "type": "object",
        "description": "Um template de mensagem, com o status que a Meta deu a ele.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "meta_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "O identificador do template na Meta."
          },
          "name": {
            "type": "string",
            "examples": [
              "confirmacao_consulta"
            ]
          },
          "category": {
            "type": "string",
            "enum": [
              "MARKETING",
              "UTILITY",
              "AUTHENTICATION"
            ]
          },
          "language_code": {
            "type": "string",
            "examples": [
              "pt_BR"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "APPROVED",
              "REJECTED",
              "PAUSED",
              "DISABLED"
            ],
            "description": "Só template `APPROVED` pode ser enviado."
          },
          "connection_id": {
            "type": "string",
            "format": "uuid"
          },
          "header": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "TEXT",
                  "IMAGE",
                  "VIDEO",
                  "DOCUMENT"
                ]
              },
              "text": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "sample_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              }
            }
          },
          "body": {
            "type": "string",
            "description": "O texto, com as variáveis no formato `{{1}}`."
          },
          "footer": {
            "type": [
              "string",
              "null"
            ]
          },
          "buttons": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "carousel_cards": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object"
            }
          },
          "body_variables": {
            "type": "integer",
            "description": "Quantos itens `body_params` precisa ter no envio."
          },
          "rejection_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Por que a Meta recusou, quando o status é `REJECTED`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TemplateList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          }
        ]
      },
      "TemplateCreate": {
        "type": "object",
        "required": [
          "connection_id",
          "name",
          "category",
          "body_text"
        ],
        "description": "Cria o template aqui e submete à Meta na mesma chamada. Ele nasce\n`PENDING` e a aprovação costuma levar de minutos a algumas horas.\nAssine `template.status_changed` para saber quando sair.\n",
        "properties": {
          "connection_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Só minúsculas, números e sublinhado.",
            "examples": [
              "confirmacao_consulta"
            ]
          },
          "category": {
            "type": "string",
            "enum": [
              "MARKETING",
              "UTILITY",
              "AUTHENTICATION"
            ]
          },
          "language_code": {
            "type": "string",
            "default": "pt_BR"
          },
          "header_type": {
            "type": "string",
            "enum": [
              "TEXT",
              "IMAGE",
              "VIDEO",
              "DOCUMENT"
            ]
          },
          "header_text": {
            "type": "string"
          },
          "header_sample_url": {
            "type": "string",
            "format": "uri",
            "description": "Exemplo de arquivo, exigido pela Meta quando o cabeçalho é de mídia."
          },
          "body_text": {
            "type": "string",
            "description": "Use `{{1}}`, `{{2}}` para as variáveis."
          },
          "footer_text": {
            "type": "string"
          },
          "buttons": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "Tag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "#22D650"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "contact",
              "conversation"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Pipeline": {
        "type": "object",
        "description": "Um funil, com as etapas na ordem em que aparecem no painel.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "position": {
            "type": "integer",
            "description": "A ordem do funil na lista do painel."
          },
          "is_default": {
            "type": "boolean",
            "description": "O funil usado quando você não informa `pipeline`."
          },
          "auto_enroll": {
            "type": "boolean",
            "description": "Se contato novo entra sozinho na primeira etapa."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "stages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "position": {
                  "type": "integer"
                },
                "color": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "Field": {
        "type": "object",
        "description": "Um campo personalizado de contato.",
        "properties": {
          "key": {
            "type": "string",
            "description": "A chave que você manda em `fields`."
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "number",
              "date",
              "select",
              "boolean"
            ]
          },
          "options": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "placeholder": {
            "type": [
              "string",
              "null"
            ],
            "description": "O texto de exemplo que aparece no painel."
          },
          "position": {
            "type": "integer",
            "description": "A ordem do campo na ficha do contato."
          }
        }
      },
      "User": {
        "type": "object",
        "description": "Um membro da organização.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "editor",
              "atendente",
              "financeiro"
            ]
          },
          "is_owner": {
            "type": "boolean",
            "description": "Dono da organização. É uma marca separada do papel."
          },
          "member_since": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "QuickReply": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "shortcut": {
            "type": "string",
            "examples": [
              "/horario"
            ]
          },
          "content": {
            "type": "string"
          }
        }
      },
      "OrgMetadata": {
        "type": "object",
        "description": "Tudo que a organização tem cadastrado e que você precisa conhecer antes\nde gravar um contato: campos, etiquetas, funis, atendentes e números.\nConsulte aqui em vez de chutar nomes.\n",
        "properties": {
          "org": {
            "type": "object",
            "description": "Identificação da organização da chave.",
            "additionalProperties": true
          },
          "custom_fields": {
            "type": "array",
            "description": "Os campos personalizados. As chaves daqui são as aceitas em `fields`.",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tag"
            }
          },
          "assignable_users": {
            "type": "array",
            "description": "Quem pode virar dono de carteira. Use o email em `assigned_user_email`.",
            "items": {
              "type": "object",
              "properties": {
                "email": {
                  "type": "string",
                  "format": "email"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "role": {
                  "type": "string"
                }
              }
            }
          },
          "whatsapp_connections": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "display_name": {
                  "type": "string"
                },
                "phone_number_id": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Campaign": {
        "type": "object",
        "description": "Um disparo de template para uma lista de contatos.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "scheduled",
              "running",
              "completed",
              "cancelled",
              "failed"
            ]
          },
          "connection_id": {
            "type": "string",
            "format": "uuid"
          },
          "template": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "language_code": {
                "type": "string"
              },
              "body_params": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "header_image_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              }
            }
          },
          "audience": {
            "type": [
              "object",
              "null"
            ],
            "description": "O filtro que definiu quem recebe."
          },
          "open_conversation": {
            "type": "string",
            "enum": [
              "always",
              "on_reply"
            ]
          },
          "metrics": {
            "type": "object",
            "properties": {
              "total_recipients": {
                "type": "integer"
              },
              "sent": {
                "type": "integer"
              },
              "delivered": {
                "type": "integer"
              },
              "read": {
                "type": "integer"
              },
              "failed": {
                "type": "integer"
              }
            }
          },
          "scheduled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CampaignList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Campaign"
                }
              }
            }
          }
        ]
      },
      "CampaignCreate": {
        "type": "object",
        "required": [
          "name",
          "connection_id",
          "template_name"
        ],
        "description": "A campanha nasce como rascunho. Dispare com `POST /campaigns/{id}/start` ou agende.",
        "properties": {
          "name": {
            "type": "string"
          },
          "connection_id": {
            "type": "string",
            "format": "uuid"
          },
          "template_name": {
            "type": "string",
            "description": "O template precisa estar `APPROVED`."
          },
          "language_code": {
            "type": "string",
            "default": "pt_BR"
          },
          "body_params": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "header_image_url": {
            "type": "string",
            "format": "uri"
          },
          "open_conversation": {
            "type": "string",
            "enum": [
              "always",
              "on_reply"
            ]
          },
          "audience": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Lista de ids de contato. Alternativa ao `audience_filter`."
          },
          "audience_filter": {
            "type": "object",
            "description": "Filtro para montar a audiência, por etiqueta ou etapa de funil.",
            "properties": {
              "tag": {
                "type": "string"
              },
              "pipeline": {
                "type": "string"
              },
              "stage": {
                "type": "string"
              }
            }
          }
        }
      },
      "CampaignRecipient": {
        "type": "object",
        "properties": {
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "phone": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "sent",
              "delivered",
              "read",
              "failed"
            ]
          },
          "wamid": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Automation": {
        "type": "object",
        "description": "Um fluxo de automação de WhatsApp.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "draft",
              "paused"
            ]
          },
          "connection_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "trigger": {
            "type": "object",
            "description": "O que coloca um contato no fluxo. O token do webhook do fluxo é credencial e não vem aqui.",
            "properties": {
              "webhook_enabled": {
                "type": "boolean"
              },
              "type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tag_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "stage_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              }
            }
          },
          "exit_conditions": {
            "type": [
              "object",
              "null"
            ]
          },
          "re_entry_cooldown_hours": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Quanto tempo o contato precisa esperar para entrar de novo."
          },
          "node_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AutomationList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Automation"
                }
              }
            }
          }
        ]
      },
      "AutomationRun": {
        "type": "object",
        "description": "A passagem de um contato por um fluxo.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "flow_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "phone": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed",
              "stopped"
            ]
          },
          "current_node_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "next_action_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "exit_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "trigger_source": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object"
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "AutomationRunList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AutomationRun"
                }
              }
            }
          }
        ]
      },
      "Webhook": {
        "type": "object",
        "description": "Um endereço seu que recebe os eventos da plataforma.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Precisa ser https e público."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Os tipos assinados. Veja `GET /webhooks/event-types`."
          },
          "active": {
            "type": "boolean"
          },
          "health": {
            "type": "object",
            "description": "Como está a entrega para este endereço.",
            "properties": {
              "failure_count": {
                "type": "integer",
                "description": "Falhas seguidas. Zera na primeira entrega que der certo."
              },
              "failing_since": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "last_success_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "disabled_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Preenchido quando desligamos o endereço após 3 dias falhando."
              },
              "disabled_reason": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "description": "O segredo que assina cada entrega. Aparece uma vez só, nesta\nresposta. Guarde agora: não há como consultá-lo depois, só\ngerar outro com `POST /webhooks/{id}/rotate-secret`.\n"
              }
            },
            "required": [
              "secret"
            ]
          }
        ]
      },
      "WebhookList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          }
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Precisa ser https. Endereço local ou de rede privada é recusado."
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            },
            "description": "Assine só o que você usa. Cada evento é uma chamada no seu servidor."
          },
          "description": {
            "type": "string",
            "description": "Aparece na lista de webhooks do painel."
          }
        }
      },
      "Delivery": {
        "type": "object",
        "description": "Uma tentativa de entregar um evento no seu endereço.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "event_id": {
            "type": "string",
            "format": "uuid"
          },
          "endpoint_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "succeeded",
              "failed",
              "exhausted"
            ]
          },
          "attempt": {
            "type": "integer",
            "description": "Tentativa número. As retentativas vão até 24 horas."
          },
          "next_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "O HTTP que o seu servidor devolveu."
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ],
            "description": "Os primeiros bytes da sua resposta, para depurar."
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "type": [
              "integer",
              "null"
            ]
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DeliveryList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Delivery"
                }
              }
            }
          }
        ]
      },
      "EventTypeInfo": {
        "type": "string",
        "description": "O identificador de um tipo de evento.",
        "examples": [
          "message.received"
        ]
      },
      "Event": {
        "type": "object",
        "description": "O corpo que chega no seu endereço, e o mesmo que `GET /events` devolve.\nO `data.object` traz o recurso no formato do `GET` correspondente.\n",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "evt_9d1b6631d791441ab347dfee019a2187"
            ]
          },
          "type": {
            "type": "string",
            "examples": [
              "contact.stage_changed"
            ]
          },
          "api_version": {
            "type": "string",
            "examples": [
              "v1"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "data": {
            "type": "object",
            "description": "O recurso mais o contexto do momento. `object` vem `null` quando o\nrecurso foi apagado entre o evento e a entrega.\n",
            "properties": {
              "object": {
                "type": [
                  "object",
                  "null"
                ]
              }
            },
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "type",
          "api_version",
          "created_at",
          "org_id",
          "data"
        ]
      },
      "EventList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          }
        ]
      },
      "BatchResult": {
        "type": "object",
        "description": "O resultado de um lote, item a item, na ordem em que vieram.",
        "properties": {
          "processed": {
            "type": "integer"
          },
          "succeeded": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "A posição do item na lista que você mandou."
                },
                "ok": {
                  "type": "boolean"
                },
                "contact_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "tags_assigned": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  }
                },
                "error": {
                  "type": "string",
                  "description": "Código do erro, quando o item falhou."
                },
                "message": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "OpenApiDocument": {
        "type": "object",
        "description": "A especificação OpenAPI 3.1 completa.",
        "additionalProperties": true
      },
      "ContactHistoryList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ContactHistoryEntry"
                }
              }
            }
          }
        ]
      },
      "ContactNoteList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ContactNote"
                }
              }
            }
          }
        ]
      },
      "ConversationEventList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ConversationEvent"
                }
              }
            }
          }
        ]
      },
      "KnowledgeDocumentList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/KnowledgeDocument"
                }
              }
            }
          }
        ]
      },
      "TagList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Tag"
                }
              }
            }
          }
        ]
      },
      "PipelineList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Pipeline"
                }
              }
            }
          }
        ]
      },
      "FieldList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          }
        ]
      },
      "UserList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        ]
      },
      "QuickReplyList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/QuickReply"
                }
              }
            }
          }
        ]
      },
      "CampaignRecipientList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CampaignRecipient"
                }
              }
            }
          }
        ]
      },
      "EventTypeList": {
        "type": "object",
        "description": "A lista de tipos de evento. Não compõe o ListEnvelope porque `data` aqui\né lista de string, e não de objeto como no resto da API.\n",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventTypeInfo"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "PartnerClient": {
        "type": "object",
        "description": "Uma organização cliente do parceiro.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "plan": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "basico",
              "pro",
              "ultra",
              null
            ]
          },
          "plan_started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "trial_ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "primary_color": {
            "type": [
              "string",
              "null"
            ]
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "custom_domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "usage": {
            "type": "object",
            "description": "Consumo do mês corrente. Vem nas listas e no detalhe.",
            "properties": {
              "period_start": {
                "type": "string",
                "format": "date-time"
              },
              "conversations_this_month": {
                "type": "integer"
              },
              "agents": {
                "type": "integer"
              },
              "members": {
                "type": "integer"
              }
            }
          }
        }
      },
      "PartnerClientList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListEnvelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PartnerClient"
                }
              }
            }
          }
        ]
      },
      "PartnerClientCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "O nome do cliente. Vira o slug do espaço."
          },
          "plan": {
            "type": "string",
            "enum": [
              "basico",
              "pro",
              "ultra"
            ],
            "description": "Sem plano, o cliente nasce em teste de 15 dias. Com plano, ele já\nnasce ativo e entra na sua cobrança. Exige assinatura de parceiro ativa.\n"
          },
          "primary_color": {
            "type": "string",
            "description": "Cor de marca do espaço."
          },
          "logo_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "PartnerClientCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PartnerClient"
          },
          {
            "type": "object",
            "properties": {
              "invite_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri",
                "description": "O link para o cliente assumir o espaço como administrador. Vale\n30 dias. Mande para ele; sem isso, o espaço fica sem dono humano.\n"
              }
            }
          }
        ]
      },
      "PartnerClientUpdate": {
        "type": "object",
        "description": "Informe ao menos um campo.",
        "properties": {
          "name": {
            "type": "string"
          },
          "primary_color": {
            "type": "string"
          },
          "logo_url": {
            "type": "string",
            "format": "uri"
          },
          "custom_domain": {
            "type": "string"
          }
        }
      },
      "PartnerKeyCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Omitido, a chave vale para todos os escopos."
          },
          "expires_in_days": {
            "type": "integer",
            "minimum": 1
          },
          "is_test": {
            "type": "boolean",
            "description": "Chave de teste, que não envia nada no WhatsApp."
          }
        }
      },
      "PartnerKeyCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid",
            "description": "O cliente onde a chave vale."
          },
          "name": {
            "type": "string"
          },
          "token": {
            "type": "string",
            "description": "A chave. Aparece uma vez só, aqui."
          },
          "token_prefix": {
            "type": "string"
          },
          "scopes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "is_test": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PartnerUsage": {
        "type": "object",
        "properties": {
          "clients": {
            "type": "integer"
          },
          "by_plan": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "conversations_this_month": {
            "type": "integer"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "client_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "plan": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "period_start": {
                  "type": "string",
                  "format": "date-time"
                },
                "conversations_this_month": {
                  "type": "integer"
                },
                "agents": {
                  "type": "integer"
                },
                "members": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "Org": {
        "type": "object",
        "description": "A organização da chave, com plano, limites e consumo do mês.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "client",
              "partner"
            ]
          },
          "is_partner": {
            "type": "boolean"
          },
          "custom_domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "plan": {
            "type": "object",
            "properties": {
              "tier": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "trial",
                  "basico",
                  "pro",
                  "ultra",
                  null
                ]
              },
              "trial_ends_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "limits": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Limite sem teto vem como `null`, porque JSON não tem infinito.",
                "properties": {
                  "agents": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "conversations_per_month": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "rag_files": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "members": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "campaign_sends_per_month": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "whatsapp": {
                    "type": "boolean"
                  },
                  "campaigns": {
                    "type": "boolean"
                  },
                  "api_write": {
                    "type": "boolean",
                    "description": "Se o plano permite escrever e enviar pela API. Ler funciona em qualquer plano."
                  },
                  "multi_agent": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          },
          "alerts": {
            "type": "array",
            "description": "O que está quebrado agora: webhook falhando, número de WhatsApp com\nerro de configuração, chave prestes a vencer. Vazio quando está tudo\ncerto. Consulte de tempos em tempos e avise o seu time.\n",
            "items": {
              "$ref": "#/components/schemas/OrgAlert"
            }
          }
        }
      },
      "OrgAlert": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "webhook_failing",
              "connection_config_error",
              "api_key_expiring"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "warning",
              "error"
            ]
          },
          "message": {
            "type": "string",
            "description": "Frase pronta em português, para mostrar direto."
          },
          "resource_id": {
            "type": "string",
            "format": "uuid",
            "description": "O recurso com problema."
          },
          "since": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "detail": {
            "type": "object",
            "description": "Campos que variam por tipo de alerta."
          }
        }
      },
      "Usage": {
        "type": "object",
        "description": "O consumo do mês corrente, para você avisar antes de o limite estourar.",
        "properties": {
          "period_start": {
            "type": "string",
            "format": "date-time"
          },
          "conversations_this_month": {
            "type": "integer"
          },
          "campaign_sends_this_month": {
            "type": "integer"
          },
          "agents": {
            "type": "integer"
          },
          "rag_files": {
            "type": "integer"
          },
          "members": {
            "type": "integer"
          }
        }
      },
      "Analytics": {
        "type": "object",
        "description": "Os mesmos números do painel de análise, no período pedido.",
        "properties": {
          "period": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date-time"
              },
              "to": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "conversations": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "resolved": {
                "type": "integer"
              },
              "open": {
                "type": "integer"
              },
              "by_channel": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "from_ads": {
                "type": "integer",
                "description": "Conversas que vieram de um anúncio Click to WhatsApp."
              }
            }
          },
          "messages": {
            "type": "object",
            "properties": {
              "inbound": {
                "type": "integer"
              },
              "outbound": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            }
          },
          "handoff": {
            "type": "object",
            "properties": {
              "requested": {
                "type": "integer"
              },
              "taken_over": {
                "type": "integer"
              },
              "rate": {
                "type": "number",
                "description": "Fração das conversas que pediram humano."
              }
            }
          },
          "ratings": {
            "type": "object",
            "properties": {
              "count": {
                "type": "integer"
              },
              "average": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          },
          "sentiment": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "conversion_events": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Quantas vezes cada evento de conversão foi detectado no período."
          }
        }
      },
      "Health": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ]
          },
          "ts": {
            "type": "string",
            "format": "date-time"
          },
          "db_ms": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tempo de uma consulta trivial ao banco. Separa \"está de pé\" de \"está rápido\"."
          }
        }
      }
    }
  },
  "webhooks": {
    "message.received": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Cliente mandou mensagem",
        "description": "Chegou mensagem de um cliente, em qualquer canal. É o evento mais usado:\nserve para registrar no seu CRM, acordar um fluxo ou avisar a equipe.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_message_received",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "message.received"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Message"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "role": {
                            "type": "string",
                            "description": "Sempre `user` neste evento."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_1a2b3c4d5e6f7890abcdef1234567890",
                "type": "message.received",
                "api_version": "v1",
                "created_at": "2026-09-08T18:30:02Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-9999-4999-8999-999999999991",
                    "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                    "role": "user",
                    "content": "Bom dia, gostaria de agendar uma avaliação.",
                    "wamid": "wamid.HBgNNTUxMTk4NzY1NDMyMQ",
                    "created_at": "2026-09-08T18:30:00Z"
                  },
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                  "role": "user"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "message.sent": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Mensagem enviada pelo agente ou pela equipe",
        "description": "A mensagem saiu daqui para o WhatsApp. Ainda não quer dizer que chegou:\npara isso, espere `message.delivered`.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_message_sent",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "message.sent"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Message"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "failed_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_2b3c4d5e6f7890abcdef1234567890ab",
                "type": "message.sent",
                "api_version": "v1",
                "created_at": "2026-09-08T18:31:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-9999-4999-8999-999999999992",
                    "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                    "role": "assistant",
                    "content": "Bom dia! Temos horário na quinta às 14h.",
                    "created_at": "2026-09-08T18:31:00Z"
                  },
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                  "previous_status": "pending",
                  "failed_reason": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "message.delivered": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Mensagem chegou no aparelho",
        "description": "O WhatsApp confirmou a entrega. Use para medir alcance real de campanha, em vez de contar só o que saiu.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_message_delivered",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "message.delivered"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Message"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_3c4d5e6f7890abcdef1234567890abcd",
                "type": "message.delivered",
                "api_version": "v1",
                "created_at": "2026-09-08T18:31:04Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-9999-4999-8999-999999999992",
                    "role": "assistant",
                    "content": "Bom dia! Temos horário na quinta às 14h.",
                    "delivery": {
                      "status": "delivered",
                      "delivered_at": "2026-09-08T18:31:04Z"
                    }
                  },
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                  "previous_status": "sent"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "message.read": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Mensagem foi lida",
        "description": "O cliente abriu a mensagem. Só chega se ele tiver a confirmação de leitura ligada no aparelho.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_message_read",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "message.read"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Message"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_4d5e6f7890abcdef1234567890abcdef",
                "type": "message.read",
                "api_version": "v1",
                "created_at": "2026-09-08T18:32:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-9999-4999-8999-999999999992",
                    "role": "assistant",
                    "content": "Bom dia! Temos horário na quinta às 14h.",
                    "delivery": {
                      "status": "read",
                      "read_at": "2026-09-08T18:32:00Z"
                    }
                  },
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                  "previous_status": "delivered"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "message.failed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Mensagem falhou no envio",
        "description": "A Meta recusou. O motivo vem em `failed_reason`. Os mais comuns são estar\nfora da janela de 24 horas com texto livre, ou o número não existir no\nWhatsApp.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_message_failed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "message.failed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Message"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "failed_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_5e6f7890abcdef1234567890abcdef12",
                "type": "message.failed",
                "api_version": "v1",
                "created_at": "2026-09-08T18:33:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-9999-4999-8999-999999999996",
                    "role": "assistant",
                    "content": "Passando para confirmar sua consulta.",
                    "delivery": {
                      "status": "failed",
                      "failed_reason": "Fora da janela de 24h"
                    }
                  },
                  "conversation_id": "c0a80101-2222-4222-8222-222222222222",
                  "previous_status": "pending",
                  "failed_reason": "Fora da janela de 24h"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.created": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Conversa nova",
        "description": "Alguém falou com você pela primeira vez, ou voltou depois de a conversa anterior ter sido encerrada.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_created",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.created"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "channel": {
                            "type": "string"
                          },
                          "contact_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_6f7890abcdef1234567890abcdef1234",
                "type": "conversation.created",
                "api_version": "v1",
                "created_at": "2026-09-08T18:30:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp",
                    "created_at": "2026-09-08T18:30:00Z"
                  },
                  "channel": "whatsapp",
                  "contact_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.handoff_requested": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Pediram atendente humano",
        "description": "A IA ou um fluxo decidiu que o caso precisa de gente, ou o cliente pediu.\nÉ o evento para acordar a equipe: mandar no Slack, abrir ticket, tocar o\nalarme.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_handoff_requested",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.handoff_requested"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "reason": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Por que o transbordo foi pedido, quando a IA soube dizer."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_7890abcdef1234567890abcdef123456",
                "type": "conversation.handoff_requested",
                "api_version": "v1",
                "created_at": "2026-09-08T18:40:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp",
                    "handoff": {
                      "requested_at": "2026-09-08T18:40:00Z",
                      "reason": "Cliente pediu falar com humano"
                    }
                  },
                  "reason": "Cliente pediu falar com humano"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.taken_over": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Humano assumiu a conversa",
        "description": "Alguém da equipe assumiu. A IA para de responder nesta conversa até ser devolvida.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_taken_over",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.taken_over"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "user_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Quem assumiu."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_890abcdef1234567890abcdef1234567",
                "type": "conversation.taken_over",
                "api_version": "v1",
                "created_at": "2026-09-08T18:42:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp",
                    "takeover": {
                      "user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd",
                      "at": "2026-09-08T18:42:00Z"
                    }
                  },
                  "user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.released": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Conversa devolvida para a IA",
        "description": "O atendente soltou a conversa. A IA volta a responder na próxima mensagem do cliente.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_released",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.released"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "previous_user_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid",
                            "description": "Quem estava atendendo até agora."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_90abcdef1234567890abcdef12345678",
                "type": "conversation.released",
                "api_version": "v1",
                "created_at": "2026-09-08T19:10:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp",
                    "takeover": null
                  },
                  "previous_user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.resolved": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Conversa encerrada",
        "description": "O atendimento foi dado por encerrado, pela equipe ou pelo encerramento\nautomático por inatividade. Bom momento para gravar o resultado no seu\nsistema ou disparar uma pesquisa.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_resolved",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.resolved"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "resolved_by": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_0abcdef1234567890abcdef123456789",
                "type": "conversation.resolved",
                "api_version": "v1",
                "created_at": "2026-09-08T19:20:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "resolved",
                    "channel": "whatsapp",
                    "resolved": {
                      "at": "2026-09-08T19:20:00Z",
                      "by": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                    }
                  },
                  "resolved_by": "c0a80101-dddd-4ddd-8ddd-dddddddddddd",
                  "previous_status": "open"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.reopened": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Conversa reaberta",
        "description": "O cliente voltou a escrever numa conversa encerrada, ou alguém reabriu na mão.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_reopened",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.reopened"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_abcdef1234567890abcdef1234567890",
                "type": "conversation.reopened",
                "api_version": "v1",
                "created_at": "2026-09-09T10:00:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp",
                    "resolved": null
                  },
                  "previous_status": "resolved"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.rated": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Cliente avaliou o atendimento",
        "description": "A nota que o cliente deu, com o comentário quando ele escreveu um. Serve para alimentar o seu painel de satisfação.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_rated",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.rated"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "score": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 5
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_bcdef1234567890abcdef1234567890a",
                "type": "conversation.rated",
                "api_version": "v1",
                "created_at": "2026-09-08T19:25:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "resolved",
                    "channel": "whatsapp",
                    "rating": {
                      "score": 5,
                      "comment": "Atendimento rápido",
                      "at": "2026-09-08T19:25:00Z"
                    }
                  },
                  "score": 5,
                  "comment": "Atendimento rápido"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "conversation.event": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Evento de conversão detectado",
        "description": "O agente reconheceu na conversa algo que você configurou como conversão,\npor exemplo um agendamento marcado ou uma proposta aceita. Quais eventos\nexistem é configuração de cada agente.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_conversation_event",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "conversation.event"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Conversation"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "name": {
                            "type": "string",
                            "description": "O nome do evento de conversão."
                          },
                          "metadata": {
                            "type": "object",
                            "description": "O que o agente extraiu junto."
                          },
                          "occurred_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_cdef1234567890abcdef1234567890ab",
                "type": "conversation.event",
                "api_version": "v1",
                "created_at": "2026-09-08T18:41:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-2222-4222-8222-222222222222",
                    "status": "open",
                    "channel": "whatsapp"
                  },
                  "name": "agendamento_marcado",
                  "metadata": {
                    "data": "2026-09-11",
                    "horario": "14:00"
                  },
                  "occurred_at": "2026-09-08T18:41:00Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.created": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato criado",
        "description": "Um contato novo entrou, por qualquer caminho: conversa, API, importação ou campanha.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_created",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.created"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_def1234567890abcdef1234567890abc",
                "type": "contact.created",
                "api_version": "v1",
                "created_at": "2026-09-08T18:30:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321",
                    "created_at": "2026-09-08T18:30:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.updated": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato alterado",
        "description": "Algum dado do cadastro mudou. Dispara também quando a mudança veio da\nprópria API, então cuide para o seu fluxo não entrar em laço gravando de\nvolta o que ele mesmo acabou de gravar.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_updated",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.updated"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_ef1234567890abcdef1234567890abcd",
                "type": "contact.updated",
                "api_version": "v1",
                "created_at": "2026-09-08T18:45:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves Souza",
                    "phone": "5511987654321",
                    "custom_fields": {
                      "plano": "Ultra"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.merged": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato fundido em outro",
        "description": "Dois cadastros da mesma pessoa viraram um. O `object` é o contato que\ndeixou de existir; `merged_into_id` aponta para o que sobreviveu. Atualize\na referência no seu sistema.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_merged",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.merged"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "merged_into_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "O contato que sobreviveu."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_f1234567890abcdef1234567890abcde",
                "type": "contact.merged",
                "api_version": "v1",
                "created_at": "2026-09-08T18:50:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1112-4111-8111-111111111112",
                    "name": "Marina A.",
                    "phone": "5511987654399"
                  },
                  "merged_into_id": "c0a80101-1111-4111-8111-111111111111"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.tag_added": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Etiqueta aplicada ao contato",
        "description": "Uma etiqueta foi colocada no contato, por alguém no painel, por um fluxo ou pela API.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_tag_added",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.tag_added"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "tag_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "tag_name": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_1234567890abcdef1234567890abcdef",
                "type": "contact.tag_added",
                "api_version": "v1",
                "created_at": "2026-09-08T18:55:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "tag_id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                  "tag_name": "Lead quente"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.tag_removed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Etiqueta removida do contato",
        "description": "A etiqueta saiu do contato. A etiqueta em si continua existindo na organização.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_tag_removed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.tag_removed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "tag_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "tag_name": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_234567890abcdef1234567890abcdef1",
                "type": "contact.tag_removed",
                "api_version": "v1",
                "created_at": "2026-09-08T19:00:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "tag_id": "c0a80101-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
                  "tag_name": "Lead quente"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.stage_changed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato mudou de etapa no funil",
        "description": "O contato andou no funil, ou foi marcado como perdido. O `source` diz de\nonde veio a mudança: painel, API ou automação.\n\nÉ o evento que mantém o seu CRM em dia com o funil daqui.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_stage_changed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.stage_changed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "pipeline_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "from_stage_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "to_stage_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "lost": {
                            "type": "boolean",
                            "description": "`true` quando a mudança foi marcar como perdido."
                          },
                          "lost_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "source": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "De onde veio a mudança: painel, api ou automação."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_34567890abcdef1234567890abcdef12",
                "type": "contact.stage_changed",
                "api_version": "v1",
                "created_at": "2026-09-08T19:05:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "pipeline_id": "c0a80101-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
                  "from_stage_id": "c0a80101-cccc-4ccc-8ccc-ccccccccccc1",
                  "to_stage_id": "c0a80101-cccc-4ccc-8ccc-cccccccccccc",
                  "lost": false,
                  "lost_reason": null,
                  "source": "api"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.assigned": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato ganhou dono de carteira",
        "description": "O contato passou a ter um responsável. O `source` diz se foi na mão, por rodízio ou por automação.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_assigned",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.assigned"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "user_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "source": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_4567890abcdef1234567890abcdef123",
                "type": "contact.assigned",
                "api_version": "v1",
                "created_at": "2026-09-08T19:06:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd",
                  "source": "manual"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.unassigned": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato ficou sem dono",
        "description": "O responsável saiu e o contato voltou para a fila geral.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_unassigned",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.unassigned"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "previous_user_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_567890abcdef1234567890abcdef1234",
                "type": "contact.unassigned",
                "api_version": "v1",
                "created_at": "2026-09-08T19:07:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321"
                  },
                  "previous_user_id": "c0a80101-dddd-4ddd-8ddd-dddddddddddd"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.opted_out": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato pediu para não receber mais",
        "description": "A partir daqui, campanha, automação e disparo avulso não saem para esta\npessoa. Propague para as suas outras listas: continuar mandando por outro\ncanal é o tipo de coisa que derruba a reputação do número.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_opted_out",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.opted_out"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_67890abcdef1234567890abcdef12345",
                "type": "contact.opted_out",
                "api_version": "v1",
                "created_at": "2026-09-08T19:08:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321",
                    "opted_out_at": "2026-09-08T19:08:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "contact.opted_in": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Contato voltou a aceitar receber",
        "description": "O opt-out foi desfeito. Guarde no seu lado a prova de que a pessoa pediu para voltar.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_contact_opted_in",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "contact.opted_in"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Contact"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_7890abcdef1234567890abcdef123456",
                "type": "contact.opted_in",
                "api_version": "v1",
                "created_at": "2026-09-09T09:00:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-1111-4111-8111-111111111111",
                    "name": "Marina Alves",
                    "phone": "5511987654321",
                    "opted_out_at": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "automation.run_started": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Automação começou para um contato",
        "description": "Um contato entrou num fluxo. O `trigger_source` diz o que o colocou lá.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_automation_run_started",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "automation.run_started"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/AutomationRun"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "flow_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "contact_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "trigger_source": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_890abcdef1234567890abcdef1234567",
                "type": "automation.run_started",
                "api_version": "v1",
                "created_at": "2026-09-08T19:10:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                    "flow_id": "c0a80101-7777-4777-8777-777777777777",
                    "phone": "5511987654321",
                    "status": "running",
                    "started_at": "2026-09-08T19:10:00Z"
                  },
                  "flow_id": "c0a80101-7777-4777-8777-777777777777",
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "phone": "5511987654321",
                  "trigger_source": "api"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "automation.run_completed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Automação terminou",
        "description": "O contato chegou ao fim do fluxo ou saiu por uma condição de saída. O `exit_reason` diz qual foi.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_automation_run_completed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "automation.run_completed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/AutomationRun"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "flow_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "contact_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "exit_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "trigger_source": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_90abcdef1234567890abcdef12345678",
                "type": "automation.run_completed",
                "api_version": "v1",
                "created_at": "2026-09-10T09:00:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                    "flow_id": "c0a80101-7777-4777-8777-777777777777",
                    "status": "completed",
                    "ended_at": "2026-09-10T09:00:00Z"
                  },
                  "flow_id": "c0a80101-7777-4777-8777-777777777777",
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "phone": "5511987654321",
                  "exit_reason": "Cliente respondeu",
                  "trigger_source": "api"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "automation.run_failed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Automação falhou",
        "description": "O fluxo parou por erro, não por regra. Costuma ser template recusado,\nnúmero sem WhatsApp ou o passo apontando para algo que foi apagado. Vale\nligar um alerta neste evento.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_automation_run_failed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "automation.run_failed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/AutomationRun"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "flow_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "contact_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "uuid"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "exit_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "trigger_source": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_0abcdef1234567890abcdef123456789",
                "type": "automation.run_failed",
                "api_version": "v1",
                "created_at": "2026-09-08T19:15:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-8a8a-4a8a-8a8a-8a8a8a8a8a8a",
                    "flow_id": "c0a80101-7777-4777-8777-777777777777",
                    "status": "failed",
                    "ended_at": "2026-09-08T19:15:00Z"
                  },
                  "flow_id": "c0a80101-7777-4777-8777-777777777777",
                  "contact_id": "c0a80101-1111-4111-8111-111111111111",
                  "phone": "5511987654321",
                  "exit_reason": "Template não aprovado",
                  "trigger_source": "api"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "campaign.started": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Campanha começou a disparar",
        "description": "O disparo saiu do rascunho e começou. Os números ainda estão zerados aqui.\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_campaign_started",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "campaign.started"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Campaign"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "total_recipients": {
                            "type": "integer"
                          },
                          "sent_count": {
                            "type": "integer"
                          },
                          "failed_count": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_abcdef1234567890abcdef1234567891",
                "type": "campaign.started",
                "api_version": "v1",
                "created_at": "2026-09-08T12:45:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-6666-4666-8666-666666666666",
                    "name": "Retorno semestral",
                    "status": "running",
                    "started_at": "2026-09-08T12:45:00Z"
                  },
                  "name": "Retorno semestral",
                  "total_recipients": 320,
                  "sent_count": 0,
                  "failed_count": 0
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "campaign.completed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Campanha terminou",
        "description": "Todos os lotes saíram. Os números finais vêm no contexto. Entrega e\nleitura continuam chegando depois, pelos eventos `message.delivered` e\n`message.read`.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_campaign_completed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "campaign.completed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Campaign"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "total_recipients": {
                            "type": "integer"
                          },
                          "sent_count": {
                            "type": "integer"
                          },
                          "failed_count": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_bcdef1234567890abcdef1234567892a",
                "type": "campaign.completed",
                "api_version": "v1",
                "created_at": "2026-09-08T12:59:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-6666-4666-8666-666666666666",
                    "name": "Retorno semestral",
                    "status": "completed",
                    "completed_at": "2026-09-08T12:59:00Z"
                  },
                  "name": "Retorno semestral",
                  "total_recipients": 320,
                  "sent_count": 318,
                  "failed_count": 2
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "template.status_changed": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Template mudou de status na Meta",
        "description": "A Meta aprovou, recusou ou pausou um template. Assine este evento em vez\nde ficar consultando: aprovação leva de minutos a horas e não tem hora\nmarcada.\n\nQuando o status vira `REJECTED`, `rejection_reason` diz o motivo.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_template_status_changed",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "template.status_changed"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Template"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "previous_status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string"
                          },
                          "rejection_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_cdef1234567890abcdef1234567893ab",
                "type": "template.status_changed",
                "api_version": "v1",
                "created_at": "2026-09-08T15:30:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-5555-4555-8555-555555555556",
                    "name": "lembrete_retorno",
                    "status": "APPROVED",
                    "category": "UTILITY"
                  },
                  "name": "lembrete_retorno",
                  "previous_status": "PENDING",
                  "status": "APPROVED",
                  "rejection_reason": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    },
    "connection.config_error": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Número de WhatsApp com erro de configuração",
        "description": "A Meta recusou uma operação por causa da configuração do número: token\nvencido, permissão retirada, número desconectado. Enquanto isso não for\nresolvido, os envios por esse número falham.\n\nLigue um alerta aqui. É o evento que avisa antes de o cliente reclamar.\n\n\nA Wevichat faz esta chamada no endereço que você cadastrou em\n`POST /webhooks`. Confira o header `Wevi-Signature` antes de confiar\nno conteúdo. Responda `200` assim que receber; se o seu servidor\nfalhar, a entrega é repetida em 1 min, 5 min, 30 min, 2 h, 12 h e 24 h.",
        "operationId": "webhook_connection_config_error",
        "security": [],
        "parameters": [
          {
            "name": "Wevi-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix>,v1=<hmac-sha256 de `<t>.<corpo cru>` com o segredo do webhook>`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event",
            "in": "header",
            "description": "O tipo do evento, repetido no header.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Event-Id",
            "in": "header",
            "description": "Id do evento. Use para não processar duas vezes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Wevi-Delivery-Id",
            "in": "header",
            "description": "Id desta tentativa de entrega.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "const": "connection.config_error"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "oneOf": [
                              {
                                "$ref": "#/components/schemas/Connection"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "message": {
                            "type": "string",
                            "description": "O que a Meta respondeu."
                          },
                          "at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "id": "evt_def1234567890abcdef1234567894abc",
                "type": "connection.config_error",
                "api_version": "v1",
                "created_at": "2026-09-08T20:00:00Z",
                "org_id": "c0a80101-0000-4000-8000-000000000000",
                "data": {
                  "object": {
                    "id": "c0a80101-4444-4444-8444-444444444444",
                    "display_name": "Clínica Bem Estar",
                    "phone_number": "+55 11 3000-0000"
                  },
                  "message": "Invalid OAuth access token",
                  "at": "2026-09-08T20:00:00Z"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido. Qualquer 2xx serve; o corpo é ignorado."
          },
          "4XX": {
            "description": "A entrega é repetida, com intervalos crescentes, por até 24 horas."
          },
          "5XX": {
            "description": "Mesma coisa: repetimos."
          }
        }
      }
    }
  }
}
