{"openapi":"3.1.0","info":{"title":"API SOLAR.IA","version":"1.0.0","description":"API pública do SOLAR.IA: contatos, mensagens, conversas, sequências, chatbots e webhooks. Autentique com um token permanente (sk_) gerado em Ajustes > Integrações > Integração via API."},"servers":[{"url":"https://api.solaria.app.br"}],"security":[{"token":[]}],"components":{"securitySchemes":{"token":{"type":"http","scheme":"bearer","bearerFormat":"sk_","description":"Token permanente do workspace"}}},"paths":{"/integrations/v1/me":{"get":{"operationId":"testar-conexao","tags":["Conta"],"summary":"Testar conexão","description":"Confere o token e devolve o workspace dono dele.\n\nUse como primeira chamada de qualquer integração: se responder 200, o token e o endereço base estão certos.","parameters":[],"responses":{"200":{"description":"Token válido","content":{"application/json":{"example":{"workspace":{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Rota Sol Viagens","status":"active"},"token":{"id":"b1c2d3e4-0000-4000-8000-000000000001","name":"ERP","source":"api"}}}}},"401":{"description":"Token ausente, inválido ou excluído","content":{"application/json":{"example":{"error":"token invalido"}}}},"403":{"description":"O plano da conta não inclui a API (vale para todas as rotas e para o MCP)","content":{"application/json":{"example":{"error":"Este recurso não está disponível no plano da sua conta. Fale com o suporte para liberar.","code":"feature_disabled"}}}}}}},"/integrations/v1/channels":{"get":{"operationId":"listar-canais","tags":["Canais"],"summary":"Listar canais","description":"Canais de WhatsApp do workspace.\n\nO `id` do canal é o `channel_id` aceito no envio de mensagens e no início de chatbots.\n\n`type`: `whatsapp_official` (API oficial da Meta) ou `whatsapp_evolution` (QR code).\n\n`status`: `inactive`, `connecting`, `active` ou `error`.","parameters":[],"responses":{"200":{"description":"Lista de canais","content":{"application/json":{"example":{"channels":[{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Comercial","type":"whatsapp_evolution","phone_number":"+5511988887777","status":"active"},{"id":"7d1e0c2b-1111-4a2b-8c3d-000000000002","name":"Oficial","type":"whatsapp_official","phone_number":"+551130000000","status":"active"}]}}}}}}},"/integrations/v1/contacts":{"get":{"operationId":"listar-contatos","tags":["Contatos"],"summary":"Listar contatos","description":"Lista e busca contatos, em ordem alfabética.\n\nCada contato traz `opted_out`: `true` quando ele está descadastrado (não recebe campanhas, sequências nem chatbots automáticos), com a data (`opted_out_at`, Unix) e a origem (`opted_out_source`).\n\nCom `opted_out=true` a lista traz só os descadastrados, dos mais recentes para os mais antigos (25 por página), com `opted_out_at` e `opted_out_source` (`cliente` = pediu na conversa, `manual` = a equipe, `api` = integração). Nesse modo, `q` busca só pelo nome.","parameters":[{"name":"q","in":"query","required":false,"description":"Busca por nome, telefone ou e-mail.","schema":{"type":"string","description":"Busca por nome, telefone ou e-mail.","example":"maria"}},{"name":"page","in":"query","required":false,"description":"Página (15 contatos por página; 25 com opted_out).","schema":{"type":"integer","description":"Página (15 contatos por página; 25 com opted_out).","default":1,"example":1}},{"name":"opted_out","in":"query","required":false,"description":"true = só os contatos descadastrados.","schema":{"type":"boolean","description":"true = só os contatos descadastrados.","example":false}}],"responses":{"200":{"description":"Página de contatos","content":{"application/json":{"example":{"contacts":[{"id":35,"name":"Maria Souza","phone_number":"+5511999990000","email":"maria@email.com","created_at":1727200000,"opted_out":false}],"total":1,"page":1}}}},"502":{"description":"Falha ao consultar o motor de mensagens","content":{"application/json":{"example":{"error":"erro ao buscar contatos"}}}}}},"post":{"operationId":"criar-contato","tags":["Contatos"],"summary":"Criar contato","description":"Cria um contato. Com telefone já cadastrado, devolve o existente.\n\nÉ idempotente pelo telefone: se já houver um contato com o mesmo número, ele é devolvido com `created: false` e status 200 — seguro para automações que rodam mais de uma vez.","parameters":[],"responses":{"200":{"description":"Telefone já cadastrado — contato existente","content":{"application/json":{"example":{"contact":{"id":35,"name":"Maria Souza","phone_number":"+5511999990000","email":"maria@email.com","created_at":1727200000,"opted_out":false},"created":false}}}},"201":{"description":"Contato criado","content":{"application/json":{"example":{"contact":{"id":35,"name":"Maria Souza","phone_number":"+5511999990000","email":"maria@email.com","created_at":1727200000,"opted_out":false},"created":true}}}},"400":{"description":"Nem nome nem telefone informados","content":{"application/json":{"example":{"error":"informe phone_number ou name"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Nome do contato. Obrigatório se não houver telefone.","example":"Maria Souza"},"phone_number":{"type":"string","description":"Telefone. Obrigatório se não houver nome.","example":"11999990000"},"email":{"type":"string","description":"E-mail.","format":"email","example":"maria@email.com"}},"required":[]},"examples":{"exemplo_1":{"summary":"Contato completo","value":{"name":"Maria Souza","phone_number":"11999990000","email":"maria@email.com"}}}}}}}},"/integrations/v1/contacts/{id}":{"get":{"operationId":"buscar-contato","tags":["Contatos"],"summary":"Buscar contato","description":"Dados de um contato pelo id.\n\nContato descadastrado vem com `opted_out: true`, a data (`opted_out_at`, Unix) e a origem (`opted_out_source`: `cliente`, `manual` ou `api`).","parameters":[{"name":"id","in":"path","required":true,"description":"Id do contato.","schema":{"type":"integer","description":"Id do contato.","example":35}}],"responses":{"200":{"description":"Contato descadastrado","content":{"application/json":{"example":{"id":35,"name":"Maria Souza","phone_number":"+5511999990000","email":"maria@email.com","created_at":1727200000,"opted_out":true,"opted_out_at":1727300000,"opted_out_source":"api"}}}},"404":{"description":"Contato não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"contato nao encontrado"}}}}}},"patch":{"operationId":"atualizar-contato","tags":["Contatos"],"summary":"Atualizar contato","description":"Altera nome, telefone ou e-mail. Só os campos enviados mudam.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do contato.","schema":{"type":"integer","description":"Id do contato.","example":35}}],"responses":{"200":{"description":"Contato atualizado","content":{"application/json":{"example":{"id":35,"name":"Maria Souza","phone_number":"+5511999990000","email":"maria@email.com","created_at":1727200000,"opted_out":false}}}},"400":{"description":"Nenhum campo para atualizar","content":{"application/json":{"example":{"error":"nada para atualizar"}}}},"404":{"description":"Contato não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"contato nao encontrado"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Novo nome.","example":"Maria Souza"},"phone_number":{"type":"string","description":"Novo telefone.","example":"11999990000"},"email":{"type":"string","description":"Novo e-mail.","format":"email","example":"maria@email.com"}},"required":[]},"examples":{"exemplo_1":{"summary":"Trocar o nome","value":{"name":"Maria Souza"}}}}}}}},"/integrations/v1/contacts/{id}/opt-out":{"post":{"operationId":"descadastrar-contato","tags":["Contatos"],"summary":"Descadastrar contato","description":"O contato para de receber mensagens automáticas.\n\nMesma regra de CRM › Contatos › Descadastrar: campanhas pulam o contato, ele sai das sequências em andamento e chatbots automáticos (API, campanha, sequência, evento, webhook) não iniciam com ele. As conversas com a equipe continuam normais.\n\nÉ idempotente: se o contato já estava descadastrado, devolve `changed: false`. Quando muda, dispara o evento `contact.opted_out` para os webhooks.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do contato.","schema":{"type":"integer","description":"Id do contato.","example":35}}],"responses":{"200":{"description":"Contato descadastrado","content":{"application/json":{"example":{"contact_id":35,"opted_out":true,"changed":true}}}},"404":{"description":"Contato não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"contato nao encontrado"}}}}}},"delete":{"operationId":"recadastrar-contato","tags":["Contatos"],"summary":"Recadastrar contato","description":"Desfaz o descadastro: o contato volta a receber campanhas e sequências.\n\nUse só quando o próprio contato pediu para voltar a receber.\n\nAs sequências que o descadastro interrompeu voltam do passo em que pararam (só as habilitadas; a inscrição nunca é duplicada): `resumed_sequences` diz quantas. As canceladas por outro motivo, como falhas de envio, continuam canceladas.\n\nSe o contato não estava descadastrado, devolve `changed: false`. Quando muda, dispara o evento `contact.opted_in`.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do contato.","schema":{"type":"integer","description":"Id do contato.","example":35}}],"responses":{"200":{"description":"Contato recadastrado","content":{"application/json":{"example":{"contact_id":35,"opted_out":false,"changed":true,"resumed_sequences":1}}}}}}},"/integrations/v1/contacts/opt-out":{"post":{"operationId":"descadastrar-por-telefone","tags":["Contatos"],"summary":"Descadastrar pelo telefone","description":"Descadastra o contato achado pelo telefone (ou pelo id no corpo).\n\nÚtil para formulários de descadastro e sistemas que só conhecem o número. O telefone aceita qualquer formato (com ou sem +55, espaços e traços). Se nenhum contato tiver o número, devolve 404 — nenhum contato é criado.","parameters":[],"responses":{"200":{"description":"Contato descadastrado","content":{"application/json":{"example":{"contact_id":35,"opted_out":true,"changed":true}}}},"400":{"description":"Nem telefone nem contato informados","content":{"application/json":{"example":{"error":"informe o id do contato, contact_id ou phone_number"}}}},"404":{"description":"Contato não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"contato nao encontrado"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phone_number":{"type":"string","description":"Telefone do contato.","example":"11999990000"},"contact_id":{"type":"integer","description":"Ou o id do contato.","example":35}},"required":[]},"examples":{"exemplo_1":{"summary":"Pelo telefone","value":{"phone_number":"11999990000"}}}}}}},"delete":{"operationId":"recadastrar-por-telefone","tags":["Contatos"],"summary":"Recadastrar pelo telefone","description":"Desfaz o descadastro do contato achado pelo telefone (ou pelo id).\n\nIgual a Recadastrar contato: as sequências interrompidas pelo descadastro voltam de onde pararam (`resumed_sequences`).","parameters":[{"name":"phone_number","in":"query","required":false,"description":"Telefone do contato.","schema":{"type":"string","description":"Telefone do contato.","example":"11999990000"}},{"name":"contact_id","in":"query","required":false,"description":"Ou o id do contato.","schema":{"type":"integer","description":"Ou o id do contato.","example":35}}],"responses":{"200":{"description":"Contato recadastrado","content":{"application/json":{"example":{"contact_id":35,"opted_out":false,"changed":true,"resumed_sequences":1}}}},"400":{"description":"Nem telefone nem contato informados","content":{"application/json":{"example":{"error":"informe o id do contato, contact_id ou phone_number"}}}},"404":{"description":"Contato não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"contato nao encontrado"}}}}}}},"/integrations/v1/tags":{"get":{"operationId":"listar-etiquetas","tags":["Etiquetas"],"summary":"Listar etiquetas","description":"Etiquetas cadastradas no workspace.","parameters":[],"responses":{"200":{"description":"Lista de etiquetas","content":{"application/json":{"example":{"tags":[{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Cliente VIP","color":"#d6b448"}]}}}}}}},"/integrations/v1/contacts/{id}/tags":{"post":{"operationId":"adicionar-etiqueta","tags":["Etiquetas"],"summary":"Adicionar etiqueta ao contato","description":"Marca o contato com uma etiqueta.\n\nDispara os chatbots de automação com o gatilho “etiqueta adicionada”, como se a etiqueta tivesse sido posta no painel.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do contato.","schema":{"type":"integer","description":"Id do contato.","example":35}}],"responses":{"200":{"description":"Etiqueta adicionada","content":{"application/json":{"example":{"contact_id":35,"tag":{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Cliente VIP"}}}}},"404":{"description":"Contato ou etiqueta não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"etiqueta nao encontrada"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tag_id":{"type":"string","description":"Id da etiqueta (veja Listar etiquetas).","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}},"required":["tag_id"]},"examples":{"exemplo_1":{"summary":"Etiqueta","value":{"tag_id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}}}}}}}},"/integrations/v1/contacts/{id}/tags/{tag_id}":{"delete":{"operationId":"remover-etiqueta","tags":["Etiquetas"],"summary":"Remover etiqueta do contato","description":"Tira uma etiqueta do contato.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do contato.","schema":{"type":"integer","description":"Id do contato.","example":35}},{"name":"tag_id","in":"path","required":true,"description":"Id da etiqueta.","schema":{"type":"string","description":"Id da etiqueta.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}}],"responses":{"200":{"description":"Etiqueta removida","content":{"application/json":{"example":{"contact_id":35,"tag":{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Cliente VIP"}}}}},"404":{"description":"Contato ou etiqueta não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"etiqueta nao encontrada"}}}}}}},"/integrations/v1/messages":{"post":{"operationId":"enviar-mensagem","tags":["Mensagens"],"summary":"Enviar mensagem","description":"Envia um texto ou um modelo para uma conversa, contato ou telefone.\n\nInforme o que enviar (`content` ou `template_id`) e para quem (`conversation_id`, `contact_id` ou `phone_number`). Sem conversa, a mensagem vai para a conversa mais recente do contato — ou uma nova é aberta no canal.\n\nCom `template_id`, no WhatsApp oficial a mensagem sai como modelo aprovado pela Meta (necessário fora da janela de 24 horas). Nos demais canais vai o texto do modelo, com `{{nome}}`, `{{primeiro_nome}}` e `{{telefone}}` preenchidos.\n\nNo chat, a mensagem aparece assinada como “Integração (API)”.\n\nEnviando para uma `conversation_id` sem modelo, a resposta traz `message_id` no lugar de `contact_id`.","parameters":[],"responses":{"201":{"description":"Mensagem enviada","content":{"application/json":{"example":{"conversation_id":120,"contact_id":35}}}},"400":{"description":"Sem conteúdo, sem destino ou id inválido","content":{"application/json":{"example":{"error":"content obrigatorio (ate 4096 caracteres) ou template_id"}}}},"404":{"description":"Conversa ou modelo não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"conversa nao encontrada"}}}},"422":{"description":"Nenhum canal conectado para abrir a conversa","content":{"application/json":{"example":{"error":"nenhum canal de WhatsApp conectado para enviar a mensagem"}}}},"502":{"description":"Falha no motor de mensagens — tente de novo","content":{"application/json":{"example":{"error":"erro ao enviar mensagem"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","description":"Texto da mensagem (até 4096 caracteres). Obrigatório sem `template_id`.","example":"Olá! Sua reserva foi confirmada."},"template_id":{"type":"string","description":"Modelo de mensagem (veja Listar modelos). Substitui `content`.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"},"conversation_id":{"type":"integer","description":"Conversa de destino. Tem prioridade sobre contato e telefone.","example":120},"contact_id":{"type":"integer","description":"Contato de destino. Usa a conversa mais recente dele (ou abre uma).","example":35},"phone_number":{"type":"string","description":"Telefone do contato. Se não existir, o contato é criado. Aceita DDD + número ou +55...","example":"11999990000"},"name":{"type":"string","description":"Nome usado ao criar o contato pelo telefone.","example":"Maria"},"channel_id":{"type":"string","description":"Canal usado para abrir a conversa quando o contato ainda não tem uma. Sem ele, usa o primeiro canal conectado.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}},"required":[]},"examples":{"exemplo_1":{"summary":"Texto por telefone","value":{"phone_number":"11999990000","name":"Maria","content":"Olá! Sua reserva foi confirmada."}},"exemplo_2":{"summary":"Modelo para um contato","value":{"contact_id":35,"template_id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}},"exemplo_3":{"summary":"Texto numa conversa","value":{"conversation_id":120,"content":"Seguimos à disposição!"}}}}}}}},"/integrations/v1/templates":{"get":{"operationId":"listar-modelos","tags":["Modelos"],"summary":"Listar modelos","description":"Modelos de mensagem ativos (os arquivados ficam de fora).\n\n`meta_status` só se aplica a modelos do WhatsApp oficial: só os `APPROVED` podem ser enviados fora da janela de 24 horas.","parameters":[],"responses":{"200":{"description":"Lista de modelos","content":{"application/json":{"example":{"templates":[{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"confirmacao_reserva","category":"utilidade","channel_type":"whatsapp_official","body":"Olá, {{primeiro_nome}}! Sua reserva está confirmada.","language":"pt_BR","meta_status":"APPROVED"}]}}}}}}},"/integrations/v1/conversations":{"get":{"operationId":"listar-conversas","tags":["Conversas"],"summary":"Listar conversas","description":"Conversas por situação, das mais recentes para as mais antigas.","parameters":[{"name":"status","in":"query","required":false,"description":"Situação das conversas.","schema":{"type":"string","description":"Situação das conversas.","enum":["open","pending","resolved","all"],"default":"open","example":"open"}},{"name":"page","in":"query","required":false,"description":"Página (25 conversas por página).","schema":{"type":"integer","description":"Página (25 conversas por página).","default":1,"example":1}}],"responses":{"200":{"description":"Página de conversas","content":{"application/json":{"example":{"conversations":[{"id":120,"status":"open","inbox_id":4,"unread_count":2,"created_at":1727200000,"last_activity_at":1727203600,"contact":{"id":35,"name":"Maria Souza","phone_number":"+5511999990000"}}],"total":1,"page":1}}}},"400":{"description":"Situação inválida","content":{"application/json":{"example":{"error":"status invalido: use open, pending, resolved ou all"}}}}}}},"/integrations/v1/conversations/{id}":{"patch":{"operationId":"atualizar-conversa","tags":["Conversas"],"summary":"Mudar situação da conversa","description":"Abre, deixa pendente ou resolve uma conversa.\n\nResolver pela API faz o mesmo que o botão Concluir do atendimento: o chatbot e o agente de IA saem da conversa, a pesquisa de satisfação (app CSAT) é enviada e a conclusão segue a preferência ao concluir do responsável pela conversa — `archive_12h` mantém a conversa 12h na lista dele e, se o cliente voltar nesse prazo, ela continua com ele; `archive_now` tira da lista e a volta do cliente é um atendimento novo (distribuição). Sem responsável, vale `archive_12h`. `close_mode` no corpo tem prioridade.\n\n`classification` registra o resultado do atendimento (app Classificação de atendimento ligado; sem o app, é ignorada). A classificação obrigatória do app vale só para quem conclui na tela: a API conclui sem ela, como o chatbot.\n\nCom o app Registro de vendas ligado (ele depende do app Classificação de atendimento), `classification.amount_cents` (inteiro, em centavos) registra a venda de uma conclusão `achieved`, creditada ao responsável pela conversa e com origem `api` — aparece em Relatórios › Vendas. Se a conversa tem uma venda registrada no atendimento e ainda em aberto, ela é fechada com o valor em vez de criar outra; resolver de novo em até 10 minutos depois de uma venda fechada corrige o valor dela (não soma). Sem o app, ou com outro resultado, o valor é ignorado. O valor obrigatório do app vale só para quem conclui na tela.\n\nQuando havia venda a gravar, a resposta traz `sale_saved`: `true` se a venda foi gravada, `false` se a conversa foi resolvida mas a venda falhou (repita o pedido para gravar). Resolver de novo como `lost` até 10 minutos depois de uma venda fechada devolve essa venda para em aberto (fora dos totais; `question` não mexe na venda) e a resposta traz `sale_reopened: true` e `sale_reopened_cents` (valor, em centavos, da venda que ficou em aberto).\n\nReabrir (`open`) ou deixar pendente apaga a conclusão.","parameters":[{"name":"id","in":"path","required":true,"description":"Id da conversa.","schema":{"type":"integer","description":"Id da conversa.","example":35}}],"responses":{"200":{"description":"Situação alterada (sale_saved só quando havia venda a gravar)","content":{"application/json":{"example":{"id":120,"status":"resolved","sale_saved":true}}}},"400":{"description":"Situação, classificação, valor da venda ou close_mode inválidos","content":{"application/json":{"example":{"error":"status invalido: use open, pending ou resolved"}}}},"404":{"description":"Conversa não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"conversa nao encontrada"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"Nova situação.","enum":["open","pending","resolved"],"example":"resolved"},"classification":{"type":"object","description":"Só com resolved: { outcome, note?, amount_cents? } — outcome `achieved` (objetivo atingido), `lost` (perdido) ou `question` (dúvida); note é uma observação de até 1000 caracteres; amount_cents é o valor da venda em centavos (só com `achieved` e o app Registro de vendas ligado; ex.: 15990 = R$ 159,90)."},"close_mode":{"type":"string","description":"Só com resolved: substitui a preferência ao concluir do responsável.","enum":["archive_12h","archive_now"],"example":"archive_now"}},"required":["status"]},"examples":{"exemplo_1":{"summary":"Resolver","value":{"status":"resolved"}},"exemplo_2":{"summary":"Resolver com classificação","value":{"status":"resolved","classification":{"outcome":"achieved","note":"Pedido fechado"},"close_mode":"archive_now"}},"exemplo_3":{"summary":"Resolver com venda","value":{"status":"resolved","classification":{"outcome":"achieved","amount_cents":15990}}},"exemplo_4":{"summary":"Reabrir","value":{"status":"open"}}}}}}}},"/integrations/v1/sequences":{"get":{"operationId":"listar-sequencias","tags":["Sequências"],"summary":"Listar sequências","description":"Sequências de mensagens do workspace.","parameters":[],"responses":{"200":{"description":"Lista de sequências","content":{"application/json":{"example":{"sequences":[{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Pós-venda","enabled":true,"step_count":3}]}}}}}}},"/integrations/v1/sequences/{id}/contacts":{"post":{"operationId":"inscrever-sequencia","tags":["Sequências"],"summary":"Inscrever contato na sequência","description":"Coloca o contato numa sequência; o primeiro passo sai no atraso configurado.","parameters":[{"name":"id","in":"path","required":true,"description":"Id da sequência.","schema":{"type":"string","description":"Id da sequência.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}}],"responses":{"201":{"description":"Contato inscrito","content":{"application/json":{"example":{"sequence_id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","contact_id":35,"status":"ativo","next_run_at":"2026-09-25T15:30:00Z"}}}},"400":{"description":"Sem contato nem telefone","content":{"application/json":{"example":{"error":"informe contact_id ou phone_number"}}}},"404":{"description":"Sequência não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"sequencia nao encontrada"}}}},"422":{"description":"A sequência ainda não tem passos","content":{"application/json":{"example":{"error":"a sequencia nao tem passos"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"integer","description":"Contato a inscrever.","example":35},"phone_number":{"type":"string","description":"Ou o telefone (cria o contato se não existir).","example":"11999990000"},"name":{"type":"string","description":"Nome usado ao criar o contato pelo telefone.","example":"Maria"}},"required":[]},"examples":{"exemplo_1":{"summary":"Por telefone","value":{"phone_number":"11999990000","name":"Maria"}}}}}}}},"/integrations/v1/chatbots":{"get":{"operationId":"listar-chatbots","tags":["Chatbots"],"summary":"Listar chatbots","description":"Chatbots de automação publicados e liberados para a API.\n\nSó aparecem os chatbots com “API” marcado em Disponibilidade (Apps > Chatbots > editar chatbot).","parameters":[],"responses":{"200":{"description":"Lista de chatbots","content":{"application/json":{"example":{"chatbots":[{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"Boas-vindas"}]}}}}}}},"/integrations/v1/chatbots/{id}/start":{"post":{"operationId":"iniciar-chatbot","tags":["Chatbots"],"summary":"Iniciar chatbot","description":"Inicia um chatbot de automação com o contato, abrindo a conversa se preciso.\n\nO chatbot é validado antes de qualquer outra coisa: se não estiver publicado ou liberado para a API, nada é criado (nem contato, nem conversa).","parameters":[{"name":"id","in":"path","required":true,"description":"Id do chatbot.","schema":{"type":"string","description":"Id do chatbot.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}}],"responses":{"201":{"description":"Chatbot iniciado","content":{"application/json":{"example":{"conversation_id":120,"contact_id":35}}}},"400":{"description":"Sem destino ou id inválido","content":{"application/json":{"example":{"error":"informe contact_id ou phone_number"}}}},"404":{"description":"Conversa não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"conversa nao encontrada"}}}},"422":{"description":"Contato descadastrado (pediu para não receber mensagens)","content":{"application/json":{"example":{"error":"o contato pediu para não receber mensagens automáticas","code":"opted_out"}}}},"502":{"description":"Falha ao abrir a conversa ou iniciar o fluxo","content":{"application/json":{"example":{"error":"erro ao iniciar o chatbot"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"conversation_id":{"type":"integer","description":"Conversa de destino. Tem prioridade sobre contato e telefone.","example":120},"contact_id":{"type":"integer","description":"Contato de destino. Usa a conversa mais recente dele (ou abre uma).","example":35},"phone_number":{"type":"string","description":"Telefone do contato. Se não existir, o contato é criado. Aceita DDD + número ou +55...","example":"11999990000"},"name":{"type":"string","description":"Nome usado ao criar o contato pelo telefone.","example":"Maria"},"channel_id":{"type":"string","description":"Canal usado para abrir a conversa quando o contato ainda não tem uma. Sem ele, usa o primeiro canal conectado.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}},"required":[]},"examples":{"exemplo_1":{"summary":"Por telefone","value":{"phone_number":"11999990000","name":"Maria"}},"exemplo_2":{"summary":"Numa conversa","value":{"conversation_id":120}}}}}}}},"/integrations/hooks/chatbots/{id}/{token}":{"post":{"operationId":"gatilho-webhook-chatbot","tags":["Chatbots"],"summary":"Gatilho por webhook","description":"Inicia um chatbot a partir de qualquer sistema, sem token sk_.\n\nPara formulários, landing pages e ferramentas que só sabem “chamar uma URL”. Copie a URL no gatilho Webhook do chatbot de automação — o `token` do caminho é a autenticação, então trate a URL como segredo.\n\nO corpo pode ter qualquer JSON (até 64 KB): o telefone é lido de `telefone`, `phone`, `phone_number`, `whatsapp` ou `celular`, e o nome de `nome` ou `name`. O objeto inteiro fica disponível no fluxo como `webhook.*` (ex.: `{{webhook.plano}}`).\n\nEste caminho fica fora de `/integrations/v1` e tem limite próprio de 120 chamadas por minuto por IP.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do chatbot.","schema":{"type":"string","description":"Id do chatbot.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}},{"name":"token","in":"path","required":true,"description":"Token do gatilho, gerado no editor do chatbot.","schema":{"type":"string","description":"Token do gatilho, gerado no editor do chatbot.","example":"a1b2c3d4e5f6"}}],"responses":{"202":{"description":"Chatbot iniciado","content":{"application/json":{"example":{"ok":true,"conversation_id":120,"contact_id":35}}}},"400":{"description":"Corpo não é um objeto JSON","content":{"application/json":{"example":{"error":"o corpo deve ser um objeto JSON"}}}},"404":{"description":"Chatbot ou token não conferem","content":{"application/json":{"example":{"error":"webhook nao encontrado"}}}},"413":{"description":"Corpo maior que 64 KB","content":{"application/json":{"example":{"error":"corpo maior que 64 KB"}}}},"422":{"description":"Contato descadastrado (pediu para não receber mensagens)","content":{"application/json":{"example":{"error":"o contato pediu para não receber mensagens automáticas","code":"opted_out","contact_id":35}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"telefone":{"type":"string","description":"Telefone do contato (ou `phone`, `phone_number`, `whatsapp`, `celular`).","example":"11999990000"},"nome":{"type":"string","description":"Nome do contato (ou `name`).","example":"Maria"}},"required":["telefone"]},"examples":{"exemplo_1":{"summary":"Formulário do site","value":{"telefone":"11999990000","nome":"Maria","plano":"Premium","origem":"landing-page"}}}}}},"security":[]}},"/integrations/v1/webhooks":{"post":{"operationId":"criar-webhook","tags":["Webhooks"],"summary":"Assinar eventos","description":"Cadastra uma URL para receber eventos. Devolve o segredo da assinatura.\n\nÉ o que o gatilho do n8n faz ao ativar um fluxo. O `secret` só aparece nesta resposta: guarde-o para validar o header `X-Solaria-Signature` de cada entrega (veja o guia Webhooks).\n\nCada workspace tem até 50 webhooks, somando os criados pela API e pela tela. Os criados pela API também aparecem em Ajustes > Integrações > Webhooks.","parameters":[],"responses":{"201":{"description":"Webhook criado","content":{"application/json":{"example":{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"ERP","url":"https://seu-sistema.com.br/hooks/solaria","events":["message.created"],"active":true,"secret":"whsec_9f8e7d6c5b4a39281706f5e4d3c2b1a0"}}}},"400":{"description":"URL ou eventos inválidos","content":{"application/json":{"example":{"error":"url invalida: use http:// ou https://"}}}},"403":{"description":"O plano da conta não inclui webhooks ou já usa todos os que ele permite","content":{"application/json":{"example":{"error":"Sua conta atingiu o limite de 5 webhooks do plano. Fale com o suporte para ampliar.","code":"plan_limit","resource":"webhooks","limit":5}}}},"422":{"description":"Limite de 50 webhooks atingido","content":{"application/json":{"example":{"error":"limite de 50 webhooks atingido: exclua os que nao usa em Ajustes > Integracoes > Webhooks","code":"webhook_limit"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Endereço que recebe os POSTs (http:// ou https://, público).","format":"uri","example":"https://seu-sistema.com.br/hooks/solaria"},"events":{"type":"array","description":"Eventos assinados (ao menos um).","items":{"type":"string","enum":["conversation.created","conversation.updated","conversation.resolved","message.created","contact.created","contact.updated","contact.opted_out","contact.opted_in"]},"example":["message.created"]},"name":{"type":"string","description":"Nome para identificar o webhook (até 120 caracteres).","default":"n8n","example":"ERP"}},"required":["url","events"]},"examples":{"exemplo_1":{"summary":"Mensagens novas","value":{"name":"ERP","url":"https://seu-sistema.com.br/hooks/solaria","events":["message.created"]}}}}}}}},"/integrations/v1/webhooks/{id}":{"get":{"operationId":"buscar-webhook","tags":["Webhooks"],"summary":"Buscar webhook","description":"Confere se um webhook ainda existe (o segredo não volta).","parameters":[{"name":"id","in":"path","required":true,"description":"Id do webhook.","schema":{"type":"string","description":"Id do webhook.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}}],"responses":{"200":{"description":"Webhook","content":{"application/json":{"example":{"id":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22","name":"ERP","url":"https://seu-sistema.com.br/hooks/solaria","events":["message.created"],"active":true}}}},"404":{"description":"Webhook não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"webhook nao encontrado"}}}}}},"delete":{"operationId":"excluir-webhook","tags":["Webhooks"],"summary":"Excluir webhook","description":"Para de enviar eventos para a URL.","parameters":[{"name":"id","in":"path","required":true,"description":"Id do webhook.","schema":{"type":"string","description":"Id do webhook.","format":"uuid","example":"3f6c2a1e-8b4d-4c1a-9e2f-7a5b0c9d1e22"}}],"responses":{"200":{"description":"Webhook excluído","content":{"application/json":{"example":{"ok":true}}}},"404":{"description":"Webhook não encontrado(a) neste workspace","content":{"application/json":{"example":{"error":"webhook nao encontrado"}}}}}}}}}