{"openapi":"3.1.0","info":{"title":"LinkZap — API pública","version":"1.0.0","summary":"Enviar e ler mensagens de WhatsApp, gerir contatos e conversas e iniciar fluxos, a partir do seu sistema.","description":"Atendimento e automação no WhatsApp. Esta API fala pelos números de WhatsApp que uma organização do LinkZap já conectou — ela não conecta números.\n\n**Autenticação:** uma chave `lz_…` em `Authorization: Bearer` ou em `x-api-key`. A chave da conta alcança todos os números; a chave de canal fala só por um (pedir outro responde 403). **Contatos são a exceção**: são da organização, e uma chave de canal enxerga todos.\n\n**Envelope:** o que volta fica dentro de `data`. `GET /contacts`, `GET /conversations` e `GET /messages` acrescentam `page`, `limit` e `total`; `GET /channels` e `GET /flows` devolvem tudo de uma vez.\n\n**Freio:** 120 chamadas por minuto por chave e 600 por organização, em janela de 60s. O 429 traz `retry-after` em segundos.\n\n**Sem CORS:** a API não responde a pedidos de outra origem, de propósito — chame do seu servidor, nunca do JavaScript de uma página.\n\n**Idioma:** identificadores, campos e valores de enum em inglês; descrições em português, que é o idioma do produto e do suporte.\n\nDocumentação em prosa: https://linkzap.orion.moe/developers · Markdown para agentes: https://linkzap.orion.moe/llms.txt","contact":{"name":"Suporte LinkZap","url":"https://linkzap.orion.moe/contact"},"license":{"name":"Proprietária — uso conforme os Termos de Uso","url":"https://linkzap.orion.moe/terms"}},"externalDocs":{"description":"A documentação em prosa, com receitas inteiras","url":"https://linkzap.orion.moe/developers"},"servers":[{"url":"https://linkzap.orion.moe","description":"Produção"}],"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"tags":[{"name":"Canais","description":"Os números conectados e o channelId que quase toda escrita pede. Comece por aqui.","externalDocs":{"url":"https://linkzap.orion.moe/developers/channels"}},{"name":"Contatos","description":"Listar, criar e atualizar pelo telefone, com etiquetas, campos próprios e opt-in.","externalDocs":{"url":"https://linkzap.orion.moe/developers/contacts"}},{"name":"Conversas","description":"As conversas da caixa, com contato, canal, responsável e o estado de atendimento.","externalDocs":{"url":"https://linkzap.orion.moe/developers/conversations"}},{"name":"Mensagens","description":"Enviar texto e mídia pelo número conectado, e ler o histórico de uma conversa.","externalDocs":{"url":"https://linkzap.orion.moe/developers/messages"}},{"name":"Fluxos","description":"Listar os fluxos e iniciar um deles para um telefone, de fora do LinkZap.","externalDocs":{"url":"https://linkzap.orion.moe/developers/flows"}},{"name":"Negócios","description":"O funil do CRM: listar os funis e as etapas, criar negócio, mover de etapa, ganhar e perder.","externalDocs":{"url":"https://linkzap.orion.moe/developers/deals"}},{"name":"Tarefas","description":"As tarefas da equipe: listar, criar com prazo e responsável, concluir e reabrir.","externalDocs":{"url":"https://linkzap.orion.moe/developers/tasks"}},{"name":"Webhook de entrada","description":"Uma URL por canal: o formulário do seu site, o CRM ou o Zapier viram contato e conversa.","externalDocs":{"url":"https://linkzap.orion.moe/developers/inbound-webhook"}}],"paths":{"/api/v1/me":{"get":{"operationId":"getMe","tags":["Canais"],"summary":"Confere a chave","description":"Diz de qual organização é a chave e se ela alcança a conta inteira (`scope: account`) ou um número só (`scope: channel`). É a primeira chamada a fazer com uma chave nova.","responses":{"200":{"description":"Os dados da chave e da organização.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityResponse"},"example":{"data":{"org":{"id":"org_...","name":"Clínica VidaVet"},"scope":"account","channel":null,"token":{"id":"tok_...","name":"CRM","prefix":"lz_ab12cd34","createdAt":"2026-09-20T12:00:00.000Z","lastUsedAt":"2026-09-21T14:02:59.000Z"}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://linkzap.orion.moe/api/v1/me \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]}},"/api/v1/channels":{"get":{"operationId":"listChannels","tags":["Canais"],"summary":"Lista os números conectados","description":"Traz o `channelId` que quase toda escrita pede, em ordem alfabética pelo rótulo. **Não é paginada.** `ready: false` vem com `reason` — o MESMO motivo que um envio recusaria com 409, o que permite checar antes em vez de tentar e tratar o erro. Uma chave de canal vê só o próprio.","responses":{"200":{"description":"Os canais da organização.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelListResponse"},"example":{"data":[{"id":"chn_9f2a...","label":"Recepção","provider":"web","phone":"5592999990000","enabled":true,"ready":true,"reason":null,"createdAt":"2026-09-02T18:11:04.000Z"},{"id":"chn_71bd...","label":"Comercial","provider":"cloud","phone":"5592988880000","enabled":true,"ready":false,"reason":"O número está desconectado.","createdAt":"2026-09-14T09:02:41.000Z"}]}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://linkzap.orion.moe/api/v1/channels \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]}},"/api/v1/contacts":{"get":{"operationId":"listContacts","tags":["Contatos"],"summary":"Lista e busca contatos","description":"Do mais recentemente atualizado para o mais antigo. **Uma chave de canal vê todos os contatos da conta** — contato pertence à organização, não ao canal.","parameters":[{"name":"query","in":"query","required":false,"description":"Busca por nome, telefone ou e-mail.","schema":{"type":"string"}},{"name":"phone","in":"query","required":false,"description":"Acha o contato exato. Aceita qualquer formatação; 422 se não for um telefone válido.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"A partir de 1.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"description":"De 1 a 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"A página de contatos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactListResponse"},"example":{"data":[{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza","email":null,"fields":{"cpf":"000.000.000-00","plano":"ouro"},"tags":["cliente","vip"],"optIn":true,"optInAt":"2026-09-20T11:02:00.000Z","optOutAt":null,"source":"api","createdAt":"2026-09-20T11:02:00.000Z","updatedAt":"2026-09-21T09:40:12.000Z"}],"page":1,"limit":50,"total":1}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://linkzap.orion.moe/api/v1/contacts?phone=5592999990000\" \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]},"post":{"operationId":"upsertContact","tags":["Contatos"],"summary":"Cria ou atualiza um contato","description":"Idempotente pelo telefone: chamar duas vezes atualiza, não duplica. O campo `created` da resposta diz qual dos dois aconteceu — e é o mesmo corpo nos dois status.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","minLength":8,"maxLength":30,"description":"Telefone com DDI + DDD + número, só dígitos (ex.: 5592999990000). Aceita +, espaço, parêntese e traço, e normaliza."},"name":{"description":"Nome do contato.","type":"string","maxLength":120},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"string","const":""}],"description":"E-mail válido, ou string vazia para limpar o que estava lá."},"fields":{"description":"Campos próprios seus. Mesclam com os que já existem — mandar um campo não apaga os outros.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","maxLength":500}},"tags":{"description":"Nomes de etiqueta. As que não existem são criadas, e aplicar uma etiqueta pode disparar um fluxo que a esteja esperando.","maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":40}},"optIn":{"description":"true registra o opt-in (origem `api`); false registra o opt-out. Ausente não mexe no que já estava.","type":"boolean"}},"required":["phone"]}}}},"responses":{"200":{"description":"O contato já existia e foi atualizado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"},"example":{"data":{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza","email":null,"fields":{"origem":"formulario-contato"},"tags":["lead-site"],"optIn":true,"optInAt":"2026-09-21T09:40:12.000Z","optOutAt":null,"source":"api","createdAt":"2026-09-21T09:40:12.000Z","updatedAt":"2026-09-21T09:40:12.000Z"},"created":true}}}},"201":{"description":"O contato foi criado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactResponse"},"example":{"data":{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza","email":null,"fields":{"origem":"formulario-contato"},"tags":["lead-site"],"optIn":true,"optInAt":"2026-09-21T09:40:12.000Z","optOutAt":null,"source":"api","createdAt":"2026-09-21T09:40:12.000Z","updatedAt":"2026-09-21T09:40:12.000Z"},"created":true}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/contacts \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"5592999990000\",\n    \"name\": \"Maria Souza\",\n    \"tags\": [\"lead-site\"],\n    \"fields\": { \"origem\": \"formulario-contato\" },\n    \"optIn\": true\n  }'"}]}},"/api/v1/conversations":{"get":{"operationId":"listConversations","tags":["Conversas"],"summary":"Lista conversas","description":"Da que teve mensagem mais recente para a mais antiga. Uma chave de canal vê só as do próprio canal.","parameters":[{"name":"status","in":"query","required":false,"description":"Filtra pelo estado de atendimento.","schema":{"type":"string","enum":["open","in_flow","resolved"]}},{"name":"channelId","in":"query","required":false,"description":"Filtra por número. Uma chave de canal que pedir outro recebe 403.","schema":{"type":"string"}},{"name":"contactId","in":"query","required":false,"description":"Todas as conversas de um contato.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"A partir de 1.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"description":"De 1 a 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"A página de conversas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListResponse"},"example":{"data":[{"id":"cnv_5ad2...","status":"open","channel":{"id":"chn_9f2a...","label":"Recepção","provider":"web"},"contact":{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza"},"assignedTo":"usr_44e1...","participants":["usr_7b20..."],"unread":2,"lastMessageAt":"2026-09-21T14:02:59.000Z","lastMessagePreview":"Pode ser quinta de manhã?","automationPausedUntil":null,"createdAt":"2026-09-19T08:30:00.000Z"}],"page":1,"limit":20,"total":37}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://linkzap.orion.moe/api/v1/conversations?status=open&limit=20\" \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]}},"/api/v1/messages":{"get":{"operationId":"listMessages","tags":["Mensagens"],"summary":"Lê o histórico de uma conversa","description":"Da mais recente para a mais antiga. O envelope traz também o `conversationId` pedido.","parameters":[{"name":"conversationId","in":"query","required":true,"description":"Obrigatório. Ache o id em `GET /api/v1/conversations`.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"A partir de 1.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"description":"De 1 a 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"includeNotes","in":"query","required":false,"description":"Inclui as notas internas da equipe. Padrão `false`.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"As mensagens da conversa.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageListResponse"},"example":{"conversationId":"cnv_5ad2...","data":[{"id":"msg_7bd0...","direction":"out","kind":"text","text":"Sua consulta está confirmada para quinta, 9h.","media":null,"author":{"kind":"automation","label":"Fluxo · Confirmação"},"status":"read","receipts":{"sent":"2026-09-21T14:02:59.000Z","delivered":"2026-09-21T14:03:04.000Z","read":"2026-09-21T14:05:22.000Z"},"externalId":"3EB0...","replyToId":null,"transcript":null,"createdAt":"2026-09-21T14:02:59.000Z"}],"page":1,"limit":20,"total":48}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://linkzap.orion.moe/api/v1/messages?conversationId=cnv_5ad2...&limit=20\" \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]},"post":{"operationId":"sendMessage","tags":["Mensagens"],"summary":"Envia uma mensagem","description":"Manda texto ou mídia pelo número conectado. Se o telefone ainda não é contato, o contato e a conversa nascem aqui. **Não é idempotente**: cada chamada envia uma mensagem.\n\nRegras que o schema não expressa:\n- Informe `phone` ou `conversationId`.\n- Informe `text`, `mediaUrl` ou `mediaId`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"description":"Por qual número falar. Obrigatório com a chave da conta; com uma chave de canal pode ser omitido, porque o escopo preenche.","type":"string","minLength":1},"phone":{"type":"string","minLength":8,"maxLength":30,"description":"Telefone com DDI + DDD + número, só dígitos (ex.: 5592999990000). Aceita +, espaço, parêntese e traço, e normaliza."},"conversationId":{"description":"Responder numa conversa que já existe. Precisa ser do mesmo canal.","type":"string","minLength":1},"text":{"description":"O texto da mensagem. Com mídia junto, vira a legenda se não houver `caption`.","type":"string","minLength":1,"maxLength":4096},"mediaUrl":{"description":"Um arquivo numa URL pública, que nós baixamos e enviamos. O endereço precisa ser público de verdade: se ele aponta para rede interna (ou redireciona para lá), ou se redireciona mais de três vezes, a resposta é 422 e nada é enviado.","type":"string","format":"uri"},"mediaId":{"description":"Um arquivo do Drive do LinkZap — mais confiável que URL para o que você reenvia sempre.","type":"string","minLength":1},"caption":{"description":"Legenda da mídia.","type":"string","maxLength":1024}}}}}},"responses":{"201":{"description":"A mensagem foi aceita e enfileirada para envio.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"},"example":{"data":{"messageId":"msg_7bd0...","conversationId":"cnv_5ad2...","channelId":"chn_9f2a..."}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"409":{"$ref":"#/components/responses/409"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/messages \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"channelId\": \"chn_9f2a...\",\n    \"phone\": \"5592999990000\",\n    \"text\": \"Sua consulta está confirmada para quinta, 9h.\"\n  }'"}]}},"/api/v1/flows":{"get":{"operationId":"listFlows","tags":["Fluxos"],"summary":"Lista os fluxos","description":"Em ordem alfabética pelo nome. **Não é paginada.** `channelId: null` significa que o fluxo atende qualquer número — por isso uma chave de canal enxerga os daquele número e os sem número.","parameters":[{"name":"enabled","in":"query","required":false,"description":"`true` traz só os ligados — os únicos que dá para iniciar.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Os fluxos da organização.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowListResponse"},"example":{"data":[{"id":"flw_2c77...","name":"Triagem","enabled":true,"channelId":null,"isMain":true,"updatedAt":"2026-09-18T20:14:00.000Z"}]}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://linkzap.orion.moe/api/v1/flows?enabled=true\" \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]}},"/api/v1/flows/{id}/start":{"post":{"operationId":"startFlow","tags":["Fluxos"],"summary":"Inicia um fluxo para um telefone","description":"Coloca a conversa daquele telefone dentro do fluxo. Um fluxo já em andamento não é interrompido.","parameters":[{"name":"id","in":"path","required":true,"description":"O id do fluxo (`GET /api/v1/flows`).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channelId":{"description":"Por qual número. Obrigatório com a chave da conta; com uma chave de canal o escopo preenche.","type":"string","minLength":1},"phone":{"type":"string","minLength":8,"maxLength":30,"description":"Telefone com DDI + DDD + número, só dígitos (ex.: 5592999990000). Aceita +, espaço, parêntese e traço, e normaliza."}},"required":["phone"]}}}},"responses":{"201":{"description":"O fluxo começou (`result: started`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartFlowResponse"},"example":{"data":{"conversationId":"cnv_5ad2...","flowId":"flw_2c77...","result":"started"}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"409":{"description":"A conversa não aceita automação agora (`result: skipped`) — mesmo corpo do 201, sem `error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartFlowResponse"},"example":{"data":{"conversationId":"cnv_5ad2...","flowId":"flw_2c77...","result":"started"}}}}},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/flows/flw_2c77.../start \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"channelId\": \"chn_9f2a...\",\n    \"phone\": \"5592999990000\"\n  }'"}]}},"/api/v1/pipelines":{"get":{"operationId":"listPipelines","tags":["Negócios"],"summary":"Lista os funis e as etapas","description":"Traz o `stageId` que criar e mover negócio pedem. **Não é paginada.** As etapas vêm na ordem do quadro. O funil padrão nasce na primeira leitura, se a conta ainda não tem nenhum.","responses":{"200":{"description":"Os funis da organização.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineListResponse"},"example":{"data":[{"id":"ppl_10aa...","name":"Vendas","isDefault":true,"stages":[{"id":"stg_1a01...","name":"Novo","position":0},{"id":"stg_77b0...","name":"Proposta","position":1}]}]}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl https://linkzap.orion.moe/api/v1/pipelines \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]}},"/api/v1/deals":{"get":{"operationId":"listDeals","tags":["Negócios"],"summary":"Lista negócios","description":"Do mexido mais recentemente para o mais antigo. **Uma chave de canal vê todos os negócios da conta** — negócio pertence à organização, como o contato.","parameters":[{"name":"status","in":"query","required":false,"description":"Filtra pelo estado.","schema":{"type":"string","enum":["open","won","lost"]}},{"name":"pipelineId","in":"query","required":false,"description":"Os negócios de um funil.","schema":{"type":"string"}},{"name":"stageId","in":"query","required":false,"description":"Os negócios de uma etapa.","schema":{"type":"string"}},{"name":"contactId","in":"query","required":false,"description":"Os negócios de um contato.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"A partir de 1.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"description":"De 1 a 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"A página de negócios.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealListResponse"},"example":{"data":[{"id":"dea_81c2...","title":"Plano anual","valueCents":299000,"status":"open","pipelineId":"ppl_10aa...","stageId":"stg_77b0...","contact":{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza"},"ownerId":"usr_44e1...","expectedCloseOn":"2026-10-31","lostReason":null,"conversationId":null,"closedAt":null,"createdAt":"2026-10-06T13:00:00.000Z","updatedAt":"2026-10-06T13:00:00.000Z"}],"page":1,"limit":20,"total":1}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://linkzap.orion.moe/api/v1/deals?status=open&limit=20\" \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]},"post":{"operationId":"createDeal","tags":["Negócios"],"summary":"Cria um negócio","description":"Para um contato que já existe. **Não é idempotente**: cada chamada cria um negócio — se o seu sistema pode repetir a chamada, confira antes com `GET /deals?contactId=&status=open`. Dispara o webhook `deal.created`.\n\nRegras que o schema não expressa:\n- Informe `contactId` OU `phone` — um dos dois, nunca os dois.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactId":{"description":"O contato do negócio. Use este OU `phone`.","type":"string","minLength":1},"phone":{"description":"O telefone de um contato que JÁ existe (crie antes com `POST /contacts`). Use este OU `contactId`.","type":"string","minLength":8,"maxLength":30},"title":{"type":"string","minLength":1,"maxLength":120,"description":"O que está sendo negociado."},"valueCents":{"description":"O valor em CENTAVOS de real: R$ 1.250,00 é `125000`. Ausente = sem valor.","type":"integer","minimum":0,"maximum":100000000000},"stageId":{"description":"A etapa de entrada (`GET /pipelines`). Ausente = a primeira etapa do funil padrão.","type":"string","minLength":1},"ownerId":{"description":"O id de uma pessoa da equipe, como responsável pelo negócio.","type":"string","minLength":1},"expectedCloseOn":{"description":"A previsão de fechamento, um dia (`AAAA-MM-DD`).","type":"string"},"conversationId":{"description":"A conversa de onde o negócio nasceu. Só é guardada se for daquele contato.","type":"string","minLength":1}},"required":["title"]}}}},"responses":{"201":{"description":"O negócio foi criado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealResponse"},"example":{"data":{"id":"dea_81c2...","title":"Plano anual","valueCents":299000,"status":"open","pipelineId":"ppl_10aa...","stageId":"stg_77b0...","contact":{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza"},"ownerId":"usr_44e1...","expectedCloseOn":"2026-10-31","lostReason":null,"conversationId":null,"closedAt":null,"createdAt":"2026-10-06T13:00:00.000Z","updatedAt":"2026-10-06T13:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/deals \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"5592999990000\",\n    \"title\": \"Plano anual\",\n    \"valueCents\": 299000,\n    \"expectedCloseOn\": \"2026-10-31\"\n  }'"}]}},"/api/v1/deals/{id}":{"post":{"operationId":"updateDeal","tags":["Negócios"],"summary":"Muda um negócio: dados, etapa ou estado","description":"Tudo ou nada: se um dos passos é recusado, nenhum é gravado. Mover dispara `deal.stage_changed`; fechar dispara `deal.won` ou `deal.lost`.\n\nRegras que o schema não expressa:\n- Envie ao menos um campo.\n- `status: lost` exige `lostReason`, e `lostReason` só vale com `status: lost`.","parameters":[{"name":"id","in":"path","required":true,"description":"O id do negócio.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"description":"Novo título.","type":"string","minLength":1,"maxLength":120},"valueCents":{"description":"Novo valor, em centavos de real.","type":"integer","minimum":0,"maximum":100000000000},"ownerId":{"description":"Novo responsável; `null` tira.","anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"expectedCloseOn":{"description":"Nova previsão de fechamento; `null` tira.","type":["string","null"]},"stageId":{"description":"Move o negócio para esta etapa (ele entra no topo dela). Só com o negócio em aberto.","type":"string","minLength":1},"status":{"description":"`won` ou `lost` fecha o negócio; `open` reabre um fechado.","type":"string","enum":["open","won","lost"]},"lostReason":{"description":"Por que se perdeu. Obrigatório com `status: lost`, e só vale com ele.","type":"string","minLength":1,"maxLength":80}}}}}},"responses":{"200":{"description":"O negócio como ficou.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealResponse"},"example":{"data":{"id":"dea_81c2...","title":"Plano anual","valueCents":299000,"status":"won","pipelineId":"ppl_10aa...","stageId":"stg_77b0...","contact":{"id":"ctt_3c81...","phone":"5592999990000","name":"Maria Souza"},"ownerId":"usr_44e1...","expectedCloseOn":"2026-10-31","lostReason":null,"conversationId":null,"closedAt":"2026-10-07T14:10:00.000Z","createdAt":"2026-10-06T13:00:00.000Z","updatedAt":"2026-10-07T14:10:00.000Z"}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"404":{"$ref":"#/components/responses/404"},"409":{"$ref":"#/components/responses/409"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/deals/dea_81c2... \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"status\": \"won\" }'"}]}},"/api/v1/tasks":{"get":{"operationId":"listTasks","tags":["Tarefas"],"summary":"Lista tarefas","description":"Da criada mais recentemente para a mais antiga. A chave de API vê as tarefas de toda a equipe.","parameters":[{"name":"status","in":"query","required":false,"description":"`open` = em aberto; `done` = concluídas.","schema":{"type":"string","enum":["open","done"]}},{"name":"contactId","in":"query","required":false,"description":"As tarefas de um contato.","schema":{"type":"string"}},{"name":"dealId","in":"query","required":false,"description":"As tarefas de um negócio.","schema":{"type":"string"}},{"name":"assigneeId","in":"query","required":false,"description":"As tarefas de uma pessoa da equipe.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"A partir de 1.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"description":"De 1 a 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"A página de tarefas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskListResponse"},"example":{"data":[{"id":"tsk_5d90...","title":"Ligar de volta","notes":null,"contactId":"ctt_3c81...","dealId":null,"assigneeId":"usr_44e1...","dueAt":"2026-10-08T02:59:59.000Z","dueHasTime":false,"done":false,"doneAt":null,"createdAt":"2026-10-06T13:00:00.000Z","updatedAt":"2026-10-06T13:00:00.000Z"}],"page":1,"limit":50,"total":1}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl \"https://linkzap.orion.moe/api/v1/tasks?status=open\" \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\""}]},"post":{"operationId":"createTask","tags":["Tarefas"],"summary":"Cria uma tarefa","description":"Com ou sem contato. **Não é idempotente.** O prazo é um dia (e, se quiser, uma hora) no fuso da organização; quem recebe a tarefa é lembrado por e-mail. Dispara o webhook `task.created`.\n\nRegras que o schema não expressa:\n- `contactId` e `phone` não vão juntos.\n- `dueTime` só vale com `dueOn`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":160,"description":"O que tem de ser feito."},"notes":{"description":"Detalhes, para quem vai fazer.","type":"string","maxLength":2000},"contactId":{"description":"O contato da tarefa. Opcional: tarefa pode não ser de ninguém.","type":"string","minLength":1},"phone":{"description":"Em vez de `contactId`: o telefone de um contato que já existe.","type":"string","minLength":8,"maxLength":30},"dealId":{"description":"O negócio da tarefa. Com ele, o contato é o do negócio.","type":"string","minLength":1},"assigneeId":{"description":"O id de quem vai fazer. É quem recebe o lembrete por e-mail.","type":"string","minLength":1},"dueOn":{"description":"O dia do prazo (`AAAA-MM-DD`), no fuso da organização.","type":"string"},"dueTime":{"description":"A hora do prazo (`HH:MM`). Sem ela, a tarefa vale o dia inteiro.","type":"string","pattern":"^\\d{2}:\\d{2}$"}},"required":["title"]}}}},"responses":{"201":{"description":"A tarefa foi criada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskResponse"},"example":{"data":{"id":"tsk_5d90...","title":"Ligar de volta","notes":null,"contactId":"ctt_3c81...","dealId":null,"assigneeId":"usr_44e1...","dueAt":"2026-10-08T02:59:59.000Z","dueHasTime":false,"done":false,"doneAt":null,"createdAt":"2026-10-06T13:00:00.000Z","updatedAt":"2026-10-06T13:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/tasks \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"5592999990000\",\n    \"title\": \"Ligar de volta\",\n    \"assigneeId\": \"usr_44e1...\",\n    \"dueOn\": \"2026-10-07\"\n  }'"}]}},"/api/v1/tasks/{id}":{"post":{"operationId":"updateTask","tags":["Tarefas"],"summary":"Conclui, reabre ou edita uma tarefa","description":"Concluir a que já está concluída não muda nada e responde 200. Concluir dispara o webhook `task.completed`.\n\nRegras que o schema não expressa:\n- Envie ao menos um campo.","parameters":[{"name":"id","in":"path","required":true,"description":"O id da tarefa.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"done":{"description":"`true` conclui a tarefa; `false` reabre.","type":"boolean"},"title":{"description":"Novo título.","type":"string","minLength":1,"maxLength":160},"notes":{"description":"Novos detalhes; `null` apaga.","anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"assigneeId":{"description":"Novo responsável; `null` tira.","anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"dueOn":{"description":"Novo dia do prazo; `null` tira o prazo.","type":["string","null"]},"dueTime":{"description":"Nova hora do prazo; `null` volta a valer o dia inteiro.","anyOf":[{"type":"string","pattern":"^\\d{2}:\\d{2}$"},{"type":"null"}]}}}}}},"responses":{"200":{"description":"A tarefa como ficou.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskResponse"},"example":{"data":{"id":"tsk_5d90...","title":"Ligar de volta","notes":null,"contactId":"ctt_3c81...","dealId":null,"assigneeId":"usr_44e1...","dueAt":"2026-10-08T02:59:59.000Z","dueHasTime":false,"done":true,"doneAt":"2026-10-07T14:10:00.000Z","createdAt":"2026-10-06T13:00:00.000Z","updatedAt":"2026-10-07T14:10:00.000Z"}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/v1/tasks/tsk_5d90... \\\n  -H \"Authorization: Bearer lz_SUA_CHAVE\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"done\": true }'"}]}},"/api/webhooks/channel/{id}":{"get":{"operationId":"getInboundWebhookContract","tags":["Webhook de entrada"],"summary":"O contrato do webhook de entrada","description":"Abrir a URL no navegador devolve o formato esperado, com o schema derivado da mesma validação que o POST usa. **Não exige autenticação** — é um dump do contrato, não dos dados.","security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"O `channelId` do número.","schema":{"type":"string"}}],"responses":{"200":{"description":"O contrato em JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundWebhookContract"}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"}}},"post":{"operationId":"postInboundWebhook","tags":["Webhook de entrada"],"summary":"Webhook de entrada: contato, mensagem ou fluxo num POST","description":"O atalho sem código: um formulário de site, Zapier, Make, n8n ou o gatilho do seu CRM viram contato e conversa. Prefira a **chave do canal** (Canais → Copiar chave de API); a chave da conta também vale, a de outro canal não.\n\nRegras que o schema não expressa:\n- Envie `message` OU `flowId`, nunca os dois.","parameters":[{"name":"id","in":"path","required":true,"description":"O `channelId` do número.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","minLength":8,"maxLength":30,"description":"Telefone com DDI + DDD + número, só dígitos (ex.: 5592999990000). Aceita +, espaço, parêntese e traço, e normaliza."},"name":{"description":"Nome do contato.","type":"string","maxLength":120},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"string","const":""}],"description":"E-mail válido."},"message":{"description":"Texto enviado ao contato pelo canal, como automação. Use este OU `flowId`.","type":"string","minLength":1,"maxLength":4096},"flowId":{"description":"Em vez de texto: inicia este fluxo na conversa do contato.","type":"string","minLength":1},"tags":{"description":"Nomes de etiquetas; as que não existem são criadas.","maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":40}},"fields":{"description":"Campos próprios seus.","type":"object","propertyNames":{"type":"string","maxLength":60},"additionalProperties":{"type":"string","maxLength":500}},"optIn":{"description":"true registra opt-in com origem `webhook`; false registra opt-out.","type":"boolean"}},"required":["phone"]}}}},"responses":{"200":{"description":"O contato já existia e foi atualizado, sem mensagem nem fluxo pedidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundWebhookResponse"},"example":{"data":{"contactId":"ctt_3c81...","created":true,"channelId":"chn_9f2a...","conversationId":"cnv_5ad2...","messageId":"msg_7bd0..."}}}}},"201":{"description":"Criou o contato, ou enviou a mensagem, ou iniciou o fluxo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundWebhookResponse"},"example":{"data":{"contactId":"ctt_3c81...","created":true,"channelId":"chn_9f2a...","conversationId":"cnv_5ad2...","messageId":"msg_7bd0..."}}}}},"400":{"$ref":"#/components/responses/400"},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"409":{"$ref":"#/components/responses/409"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"500":{"$ref":"#/components/responses/500"},"503":{"$ref":"#/components/responses/503"}},"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl -X POST https://linkzap.orion.moe/api/webhooks/channel/SEU_CHANNEL_ID \\\n  -H \"x-api-key: lz_CHAVE_DO_CANAL\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone\": \"5592999990000\",\n    \"name\": \"Maria Souza\",\n    \"message\": \"Oi, Maria! Recebemos o seu pedido de contato. Em que posso ajudar?\",\n    \"tags\": [\"lead-site\"],\n    \"fields\": { \"origem\": \"formulario-contato\" },\n    \"optIn\": true\n  }'"}]}}},"webhooks":{"message.received":{"post":{"operationId":"onMessageReceived","summary":"Mensagem recebida","description":"O contato mandou uma mensagem — o gatilho mais usado.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"message.received"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"message.received","data":{"conversationId":"cnv_...","contactId":"ctt_...","channelId":"chn_...","messageId":"msg_...","phone":"5592999990000","text":"Oi, queria marcar uma consulta","kind":"text","event":"message.received","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"message.sent":{"post":{"operationId":"onMessageSent","summary":"Mensagem enviada","description":"Saiu uma mensagem daqui — por uma pessoa da equipe, pela Aura, por um fluxo, por campanha ou pela própria API.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"message.sent"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"message.sent","data":{"conversationId":"cnv_...","contactId":"ctt_...","channelId":"chn_...","messageId":"msg_...","phone":"5592999990000","text":"Claro! Que dia fica bom?","author":"automation","event":"message.sent","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"conversation.opened":{"post":{"operationId":"onConversationOpened","summary":"Conversa aberta","description":"Uma conversa resolvida voltou para a fila.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"conversation.opened"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"conversation.opened","data":{"conversationId":"cnv_...","contactId":"ctt_...","channelId":"chn_...","status":"open","event":"conversation.opened","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"conversation.resolved":{"post":{"operationId":"onConversationResolved","summary":"Conversa resolvida","description":"O atendimento foi encerrado.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"conversation.resolved"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"conversation.resolved","data":{"conversationId":"cnv_...","contactId":"ctt_...","channelId":"chn_...","status":"resolved","event":"conversation.resolved","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"conversation.assigned":{"post":{"operationId":"onConversationAssigned","summary":"Conversa atribuída","description":"A conversa passou a ter (ou deixou de ter) responsável.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"conversation.assigned"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"conversation.assigned","data":{"conversationId":"cnv_...","assignedTo":"usr_...","by":"usr_...","event":"conversation.assigned","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"conversation.department_changed":{"post":{"operationId":"onConversationDepartmentChanged","summary":"Conversa mudou de setor","description":"O setor PRINCIPAL da conversa mudou: ela foi encaminhada para outro time.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"conversation.department_changed"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"conversation.department_changed","data":{"conversationId":"cnv_...","departmentId":"dpt_...","by":"usr_...","event":"conversation.department_changed","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"conversation.participants_changed":{"post":{"operationId":"onConversationParticipantsChanged","summary":"Participantes da conversa mudaram","description":"Alguém entrou ou saiu da conversa além do responsável. Vem a lista inteira que ficou, e o responsável do momento.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"conversation.participants_changed"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"conversation.participants_changed","data":{"conversationId":"cnv_...","assignedTo":"usr_...","participants":["usr_...","usr_..."],"by":"usr_...","event":"conversation.participants_changed","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"conversation.departments_changed":{"post":{"operationId":"onConversationDepartmentsChanged","summary":"Setores adicionais da conversa mudaram","description":"Um setor foi adicionado ou tirado além do principal. Vem a lista inteira que ficou, e o setor principal do momento.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"conversation.departments_changed"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"conversation.departments_changed","data":{"conversationId":"cnv_...","departmentId":"dpt_...","departmentIds":["dpt_..."],"by":"usr_...","event":"conversation.departments_changed","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"contact.created":{"post":{"operationId":"onContactCreated","summary":"Contato criado","description":"Um telefone novo entrou na base — por mensagem recebida, pela API, por importação ou pelo webhook de entrada.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"contact.created"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"contact.created","data":{"contactId":"ctt_...","phone":"5592999990000","name":"Maria","source":"whatsapp","event":"contact.created","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"contact.opt_in":{"post":{"operationId":"onContactOptIn","summary":"Contato deu opt-in","description":"O contato autorizou receber mensagens — é o que libera campanha e sequência.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"contact.opt_in"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"contact.opt_in","data":{"contactId":"ctt_...","phone":"5592999990000","source":"api","event":"contact.opt_in","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"contact.opt_out":{"post":{"operationId":"onContactOptOut","summary":"Contato pediu opt-out","description":"O contato pediu para não receber mais. Respeite no seu sistema também.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"contact.opt_out"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"contact.opt_out","data":{"contactId":"ctt_...","phone":"5592999990000","source":"api","event":"contact.opt_out","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"contact.updated":{"post":{"operationId":"onContactUpdated","summary":"Contato alterado","description":"Mudou o nome, o telefone, o e-mail, um campo, uma etiqueta ou o responsável de um contato. `changed` diz o quê; releia o contato com `GET /contacts?phone=`. Uma mesma chamada pode gerar mais de um (um por tipo de mudança: nome, campos, etiquetas), e o de um contato recém-criado sai depois do `contact.created` dele. Opt-in e opt-out têm evento próprio.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"contact.updated"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"contact.updated","data":{"contactId":"ctt_...","phone":"5592999990000","name":"Maria Souza","changed":["fields"],"event":"contact.updated","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"deal.created":{"post":{"operationId":"onDealCreated","summary":"Negócio criado","description":"Um negócio entrou no funil — por uma pessoa, por um fluxo, pela Aura ou pela API.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"deal.created"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"deal.created","data":{"dealId":"dea_...","contactId":"ctt_...","phone":"5592999990000","title":"Plano anual","valueCents":299000,"status":"open","pipelineId":"ppl_...","stageId":"stg_...","stage":"Novo","ownerId":"usr_...","lostReason":null,"conversationId":"cnv_...","event":"deal.created","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"deal.stage_changed":{"post":{"operationId":"onDealStageChanged","summary":"Negócio mudou de etapa","description":"O negócio foi para outra etapa do funil. Vem a etapa nova e, em `fromStageId`/`fromStage`, a anterior. Reordenar dentro da mesma etapa não dispara.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"deal.stage_changed"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"deal.stage_changed","data":{"dealId":"dea_...","contactId":"ctt_...","phone":"5592999990000","title":"Plano anual","valueCents":299000,"status":"open","pipelineId":"ppl_...","stageId":"stg_...","stage":"Proposta","ownerId":"usr_...","lostReason":null,"conversationId":"cnv_...","fromStageId":"stg_...","fromStage":"Em contato","event":"deal.stage_changed","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"deal.won":{"post":{"operationId":"onDealWon","summary":"Negócio ganho","description":"O negócio foi fechado como ganho.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"deal.won"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"deal.won","data":{"dealId":"dea_...","contactId":"ctt_...","phone":"5592999990000","title":"Plano anual","valueCents":299000,"status":"won","pipelineId":"ppl_...","stageId":"stg_...","stage":"Negociação","ownerId":"usr_...","lostReason":null,"conversationId":"cnv_...","event":"deal.won","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"deal.lost":{"post":{"operationId":"onDealLost","summary":"Negócio perdido","description":"O negócio foi fechado como perdido. `lostReason` traz o motivo.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"deal.lost"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"deal.lost","data":{"dealId":"dea_...","contactId":"ctt_...","phone":"5592999990000","title":"Plano anual","valueCents":299000,"status":"lost","pipelineId":"ppl_...","stageId":"stg_...","stage":"Proposta","ownerId":"usr_...","lostReason":"Preço","conversationId":"cnv_...","event":"deal.lost","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"task.created":{"post":{"operationId":"onTaskCreated","summary":"Tarefa criada","description":"Uma tarefa foi criada para a equipe. `contactId` e `phone` vêm nulos em tarefa que não é de um contato.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"task.created"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"task.created","data":{"taskId":"tsk_...","title":"Ligar de volta","contactId":"ctt_...","phone":"5592999990000","dealId":null,"assigneeId":"usr_...","dueAt":"2026-10-08T02:59:59.000Z","doneAt":null,"event":"task.created","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"task.completed":{"post":{"operationId":"onTaskCompleted","summary":"Tarefa concluída","description":"Alguém concluiu a tarefa. Reabrir não dispara evento.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"task.completed"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"task.completed","data":{"taskId":"tsk_...","title":"Ligar de volta","contactId":"ctt_...","phone":"5592999990000","dealId":null,"assigneeId":"usr_...","dueAt":"2026-10-08T02:59:59.000Z","doneAt":"2026-10-07T14:10:00.000Z","event":"task.completed","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}},"ping":{"post":{"operationId":"onPing","summary":"Teste de entrega","description":"Você apertou o botão de avião na tela de Integrações. Não corresponde a nada que tenha acontecido na conta — serve para conferir que a sua URL responde e que a assinatura confere.\n\nAssinado com HMAC-SHA256 do corpo CRU. Responda 2xx em até 10 segundos e processe depois; insistimos 6 vezes com espera crescente.","parameters":[{"name":"X-LinkZap-Event","in":"header","required":true,"description":"O nome do evento, para rotear sem abrir o corpo.","schema":{"type":"string","const":"ping"}},{"name":"X-LinkZap-Delivery","in":"header","required":true,"description":"O id desta entrega — a sua chave de idempotência. A mesma entrega pode chegar duas vezes.","schema":{"type":"string"}},{"name":"X-LinkZap-Signature","in":"header","required":true,"description":"`sha256=` seguido do HMAC-SHA256 do corpo cru com o seu segredo.","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}},{"name":"User-Agent","in":"header","required":true,"schema":{"type":"string","const":"LinkZap-Webhooks/1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"},"example":{"id":"whd_8e31...","event":"ping","data":{"by":"voce@exemplo.com","event":"ping","occurredAt":"2026-09-21T14:03:11.000Z"}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx serve; processe fora do pedido."},"default":{"description":"Qualquer outro status conta como falha e entra no recuo (até 6 tentativas)."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"lz_ + 40 caracteres","description":"`Authorization: Bearer lz_…`"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Para ferramentas que não deixam mexer no `Authorization`. Aceita a mesma chave."}},"responses":{"400":{"description":"O corpo enviado não é JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Chave ausente, inválida ou revogada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"A chave pertence a outro canal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Não existe nesta organização.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Existe, mas não dá agora — o motivo vem em `error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Dados inválidos. Quando o problema é de forma, vem com `issues[]` apontando o campo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Freio: 120 chamadas por minuto por chave e 600 por organização.","headers":{"retry-after":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erro interno.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Dependência indisponível neste servidor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"A frase em português, escrita para aparecer no seu log ou para a sua equipe ler."},"issues":{"type":"array","description":"Só nos 422 de forma. Um 422 de regra de negócio (telefone que não normaliza, conversa de outro canal) vem sem ele.","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"],"additionalProperties":false}}},"required":["error"],"additionalProperties":false},"Org":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"ChannelRef":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"}},"required":["id","label"],"additionalProperties":false},"ApiToken":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"Os dez primeiros caracteres — é tudo o que guardamos além do hash."},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","prefix","createdAt","lastUsedAt"],"additionalProperties":false},"Identity":{"type":"object","properties":{"org":{"oneOf":[{"$ref":"#/components/schemas/Org"},{"type":"null"}]},"scope":{"type":"string","enum":["account","channel"],"description":"`account` alcança todos os números; `channel` fala só por um."},"channel":{"oneOf":[{"$ref":"#/components/schemas/ChannelRef"},{"type":"null"}],"description":"O número ao qual a chave está presa, quando `scope` é `channel`."},"token":{"oneOf":[{"$ref":"#/components/schemas/ApiToken"},{"type":"null"}]}},"required":["org","scope","channel","token"],"additionalProperties":false},"Channel":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","description":"O nome que a equipe deu ao número. Pode mudar a qualquer momento — guarde o `id`."},"provider":{"type":"string","enum":["web","cloud"],"description":"`web` = conectado por QR; `cloud` = conta oficial da Meta (com janela de 24 h para texto livre)."},"phone":{"type":["string","null"]},"enabled":{"type":"boolean"},"ready":{"type":"boolean","description":"Se um envio por este canal passaria agora."},"reason":{"type":["string","null"],"description":"Quando `ready` é false, o motivo em palavras — o MESMO que um envio recusaria com 409."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","label","provider","phone","enabled","ready","reason","createdAt"],"additionalProperties":false},"Contact":{"type":"object","properties":{"id":{"type":"string"},"phone":{"type":"string"},"name":{"type":["string","null"]},"email":{"type":["string","null"]},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Campos próprios da organização."},"tags":{"type":"array","items":{"type":"string"}},"optIn":{"type":"boolean","description":"Derivado: só é true se há opt-in registrado e NENHUM opt-out depois dele."},"optInAt":{"type":["string","null"],"format":"date-time"},"optOutAt":{"type":["string","null"],"format":"date-time"},"source":{"type":["string","null"],"description":"De onde o contato veio: `api`, `webhook`, `whatsapp`, importação…"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","phone","name","email","fields","tags","optIn","optInAt","optOutAt","source","createdAt","updatedAt"],"additionalProperties":false},"ContactRef":{"type":"object","properties":{"id":{"type":"string"},"phone":{"type":"string"},"name":{"type":["string","null"]}},"required":["id","phone","name"],"additionalProperties":false},"ConversationChannel":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"provider":{"type":"string","enum":["web","cloud"]}},"required":["id","label","provider"],"additionalProperties":false},"Conversation":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["open","in_flow","resolved"],"description":"`in_flow` é conversa conduzida por um fluxo — ela NÃO aparece na aba “Abertos” do painel."},"channel":{"$ref":"#/components/schemas/ConversationChannel"},"contact":{"oneOf":[{"$ref":"#/components/schemas/ContactRef"},{"type":"null"}],"description":"Nulo em conversa cujo contato foi apagado."},"assignedTo":{"type":["string","null"],"description":"O RESPONSÁVEL pela conversa. Nulo = ninguém está nela (a fila)."},"participants":{"type":"array","items":{"type":"string"},"description":"Quem mais da equipe está na conversa além do responsável, na ordem em que entrou. Sempre vazio quando `assignedTo` é nulo."},"unread":{"type":"integer","description":"A contagem que a equipe vê no painel — não é um estado do WhatsApp."},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"lastMessagePreview":{"type":["string","null"]},"automationPausedUntil":{"type":["string","null"],"format":"date-time","description":"Até quando a automação está calada aqui — é o que acontece depois que uma pessoa responde."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","status","channel","contact","assignedTo","participants","unread","lastMessageAt","lastMessagePreview","automationPausedUntil","createdAt"],"additionalProperties":false},"MessageMedia":{"type":"object","properties":{"url":{"type":["string","null"],"description":"Nulo enquanto `pending` for true — preferimos isso a entregar um link que não abre."},"mime":{"type":["string","null"]},"name":{"type":["string","null"]},"size":{"type":["integer","null"]},"voice":{"type":"boolean"},"pending":{"type":"boolean","description":"O arquivo ainda não foi baixado para cá."}},"required":["url","mime","name","size","voice","pending"],"additionalProperties":false},"MessageAuthor":{"type":"object","properties":{"kind":{"type":"string","enum":["contact","team","automation"]},"label":{"type":["string","null"],"description":"O nome da pessoa, ou a origem da automação (`Aura`, `Fluxo · X`, `Campanha`, `API`)."}},"required":["kind","label"],"additionalProperties":false},"Message":{"type":"object","properties":{"id":{"type":"string"},"direction":{"type":"string","enum":["in","out","note"],"description":"`note` só aparece com `includeNotes=true`."},"kind":{"type":"string","description":"`text`, `image`, `audio`, `document`…"},"text":{"type":["string","null"]},"media":{"oneOf":[{"$ref":"#/components/schemas/MessageMedia"},{"type":"null"}]},"author":{"$ref":"#/components/schemas/MessageAuthor"},"status":{"type":["string","null"]},"receipts":{"type":["object","null"],"additionalProperties":true,"description":"O horário mais cedo de cada estado (`sent`, `delivered`, `read`)."},"externalId":{"type":["string","null"],"description":"O id da mensagem no WhatsApp."},"replyToId":{"type":["string","null"]},"transcript":{"type":["string","null"],"description":"A transcrição de uma nota de voz, quando a Aura já transcreveu."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","direction","kind","text","media","author","status","receipts","externalId","replyToId","transcript","createdAt"],"additionalProperties":false},"Flow":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"enabled":{"type":"boolean"},"channelId":{"type":["string","null"],"description":"Nulo significa que o fluxo atende QUALQUER número — não que ele esteja sem canal."},"isMain":{"type":"boolean","description":"O fluxo principal: o que responde quando nenhum outro gatilho combina."},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","enabled","channelId","isMain","updatedAt"],"additionalProperties":false},"SentMessage":{"type":"object","properties":{"messageId":{"type":"string"},"conversationId":{"type":"string"},"channelId":{"type":"string"}},"required":["messageId","conversationId","channelId"],"additionalProperties":false},"StartedFlow":{"type":"object","properties":{"conversationId":{"type":"string"},"flowId":{"type":"string"},"result":{"type":"string","enum":["started","skipped"],"description":"`started` vem com 201; `skipped` vem com 409 — e nesse caso o corpo é este mesmo, sem `error`."}},"required":["conversationId","flowId","result"],"additionalProperties":false},"InboundWebhookResult":{"type":"object","properties":{"contactId":{"type":"string"},"created":{"type":"boolean","description":"O contato nasceu nesta chamada."},"channelId":{"type":"string"},"conversationId":{"type":"string","description":"Só quando houve mensagem ou fluxo."},"messageId":{"type":"string","description":"Só quando houve mensagem."},"flow":{"type":"string","enum":["started"],"description":"Só quando houve fluxo."}},"required":["contactId","created","channelId"],"additionalProperties":false},"WebhookEnvelope":{"type":"object","properties":{"id":{"type":"string","description":"O id da ENTREGA. É a sua chave de idempotência — o mesmo id pode chegar duas vezes."},"event":{"type":"string"},"data":{"type":"object","additionalProperties":true,"description":"Os campos do evento, mais `event` e `occurredAt` (ISO-8601 em UTC)."}},"required":["id","event","data"],"additionalProperties":false},"InboundWebhookContract":{"type":"object","properties":{"webhook":{"type":"string"},"method":{"type":"string"},"auth":{"type":"string"},"docs":{"type":"string"},"openapi":{"type":"string"},"rules":{"type":"array","items":{"type":"string"}},"schema":{"type":"object","additionalProperties":true,"description":"O JSON Schema do corpo, derivado da mesma validação que o POST usa."}},"required":["webhook","method","auth","schema"],"additionalProperties":false},"PipelineStage":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"integer","description":"A ordem da etapa no funil, a partir de 0."}},"required":["id","name","position"],"additionalProperties":false},"Pipeline":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"isDefault":{"type":"boolean","description":"O funil que recebe o negócio criado sem `stageId`."},"stages":{"type":"array","items":{"$ref":"#/components/schemas/PipelineStage"},"description":"Na ordem do quadro."}},"required":["id","name","isDefault","stages"],"additionalProperties":false},"Deal":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"valueCents":{"type":"integer","description":"Em CENTAVOS de real: `125000` é R$ 1.250,00. Zero = sem valor."},"status":{"type":"string","enum":["open","won","lost"]},"pipelineId":{"type":"string"},"stageId":{"type":"string","description":"A etapa em que o negócio está. Negócio fechado guarda a etapa em que estava ao fechar."},"contact":{"$ref":"#/components/schemas/ContactRef"},"ownerId":{"type":["string","null"],"description":"O responsável pelo negócio (uma pessoa da equipe)."},"expectedCloseOn":{"type":["string","null"],"format":"date","description":"A previsão de fechamento, um dia."},"lostReason":{"type":["string","null"],"description":"Só em `status: lost`."},"conversationId":{"type":["string","null"],"description":"A conversa de onde o negócio nasceu, quando foi criado de dentro do atendimento."},"closedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","title","valueCents","status","pipelineId","stageId","contact","ownerId","expectedCloseOn","lostReason","conversationId","closedAt","createdAt","updatedAt"],"additionalProperties":false},"Task":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"notes":{"type":["string","null"]},"contactId":{"type":["string","null"],"description":"Nulo em tarefa que não é de um contato."},"dealId":{"type":["string","null"]},"assigneeId":{"type":["string","null"],"description":"Quem vai fazer — e quem recebe o lembrete por e-mail."},"dueAt":{"type":["string","null"],"format":"date-time","description":"O prazo, em UTC. Com `dueHasTime: false` é o FIM do dia no fuso da organização."},"dueHasTime":{"type":"boolean","description":"false = o prazo é um dia inteiro; true = tem hora marcada."},"done":{"type":"boolean"},"doneAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","title","notes","contactId","dealId","assigneeId","dueAt","dueHasTime","done","doneAt","createdAt","updatedAt"],"additionalProperties":false},"IdentityResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Identity"}},"required":["data"],"additionalProperties":false},"ChannelListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Channel"}}},"required":["data"],"additionalProperties":false},"FlowListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Flow"}}},"required":["data"],"additionalProperties":false},"ContactListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"],"additionalProperties":false},"ContactResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Contact"},"created":{"type":"boolean","description":"true no 201 (criou), false no 200 (atualizou)."}},"required":["data","created"],"additionalProperties":false},"ConversationListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Conversation"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"],"additionalProperties":false},"MessageListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"conversationId":{"type":"string"}},"required":["data","page","limit","total","conversationId"],"additionalProperties":false},"SendMessageResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SentMessage"}},"required":["data"],"additionalProperties":false},"StartFlowResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/StartedFlow"}},"required":["data"],"additionalProperties":false},"InboundWebhookResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InboundWebhookResult"}},"required":["data"],"additionalProperties":false},"PipelineListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Pipeline"}}},"required":["data"],"additionalProperties":false},"DealListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Deal"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"],"additionalProperties":false},"DealResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Deal"}},"required":["data"],"additionalProperties":false},"TaskListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"}},"required":["data","page","limit","total"],"additionalProperties":false},"TaskResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Task"}},"required":["data"],"additionalProperties":false}}}}