API e webhooks — conecte a Craft ao seu CRM ou site
Como controlar a Craft com requisições autenticadas por chave e receber no seu próprio servidor eventos sobre novos contatos, cliques em botões, pagamentos e posts.
Você pode conectar a Craft ao seu CRM, ao site de um cliente ou a qualquer serviço seu. Tudo o que o conector MCP faz está disponível como uma requisição HTTPS simples com uma chave: funis, contatos, disparos, posts, carrosséis, imagens. Os webhooks funcionam no sentido contrário: a Craft envia um evento para o seu servidor quando aparece um novo contato, alguém clica num botão, atinge a meta de um funil, paga, ou um post é publicado.
Como funciona#
- Na Craft, você cria uma chave e escolhe o que ela pode fazer: só ler, ou trabalhar com funis, contatos, disparos, posts e assim por diante.
- Seu servidor envia uma requisição para
https://craftopen.space/api/v1/tools/<method>com a chave num cabeçalho. Os parâmetros do método vão no corpo JSON da requisição. - A Craft executa o método na sua conta — exatamente como se você fizesse no site ou pedisse à sua IA pelo conector MCP, com as mesmas verificações e limites.
- Para eventos, você adiciona um webhook — o endereço do seu servidor. A Craft envia para lá uma requisição assinada e tenta de novo se o seu servidor não responder.
O que você precisa#
- Qualquer plano: chaves e webhooks podem ser criados em todos os planos, inclusive no gratuito.
- Um servidor ou serviço capaz de enviar e receber requisições HTTPS: seu próprio código, Make, n8n, Zapier ou um CRM com webhooks de entrada.
Passo 1. Crie uma chave#
Menu do perfil → API e webhooks (ou Configurações → API e webhooks) → Nova chave.
- Dê à chave um nome que você vá reconhecer depois: "HubSpot", "Site do cliente".
- Escolha o que a chave pode fazer. Por padrão, uma chave nova só pode ler. Todo o resto é ativado com caixas de seleção: funis, contatos, disparos, posts, conteúdo, Fábrica de conteúdo, contas. "Tudo" abre todas as capacidades, inclusive as adicionadas depois.
- Escolha como a chave publica posts e disparos: - Só rascunhos — tudo é salvo como rascunho e você mesmo envia na Craft; - Agendado — no mínimo em 10 minutos, para dar tempo de cancelar; - Na hora — publica e envia no momento da requisição.
- Defina o limite diário de gasto com imagens e quantos disparos por dia a chave pode enviar de um bot.
- Clique em Criar chave e copie na hora.
🔴 A chave é mostrada uma única vez. A Craft guarda só a impressão digital dela e não consegue recuperá-la. Perdeu? Revogue e crie uma nova. Nunca coloque a chave no código de uma página do site ou num app de celular — todo visitante a veria. A chave fica só no servidor.
Você pode mudar as permissões e configurações de uma chave a qualquer momento em "Configurações" — as mudanças valem em até um minuto. "Revogar" desativa a chave na hora.
Passo 2. Sua primeira requisição#
curl -X POST https://craftopen.space/api/v1/tools/list_funnels \
-H "Authorization: Bearer craft_your_key" \
-H "Content-Type: application/json" \
-d '{}'
Uma resposta bem-sucedida sempre tem esta forma — os dados em si ficam em data:
{"ok": true, "data": {"funnels": [ ... ]}}
Se algo estiver errado, você recebe "ok": false e um motivo claro:
{"ok": false, "error": {"code": "funnel_not_found", "message": "Воронка не найдена."}}
⚠️ No momento, as mensagens de erro são escritas em russo. Construa sua lógica com base em error.code — ele
é estável e não depende do idioma.
Métodos disponíveis#
Todos os métodos e seus parâmetros com descrições:
- na Craft:
GET https://craftopen.space/api/v1/toolscom a sua chave — a lista diz qual permissão cada método exige e se esta chave pode chamá-lo; - uma descrição OpenAPI: craftopen.space/api/v1/openapi.json — Postman, Insomnia e geradores de clientes a entendem.
Os métodos são os mesmos do conector MCP. Os mais comuns:
| Tarefa | Método | Permissão da chave |
|---|---|---|
| Listar funis e suas estatísticas | list_funnels, get_funnel_stats |
leitura |
| Encontrar inscritos do bot | find_contacts |
leitura |
| Card do inscrito | get_contact |
leitura |
| Adicionar ou remover uma tag | tag_contacts |
contatos |
| Rodar um funil para uma pessoa | run_funnel_for_contact |
contatos, modo "Na hora" |
| Post agendado | list_publishing_accounts → schedule_post |
posts |
| Disparo no Telegram | save_broadcast_draft → send_broadcast_test → send_broadcast |
disparos |
| Carrossel a partir do seu texto | create_carousel, render_carousel |
conteúdo |
| Imagem por créditos | generate_image |
conteúdo |
GET https://craftopen.space/api/v1/me mostra qual chave você está usando, as permissões dela e quantas
requisições restam hoje.
Repetir sem duplicar#
Se uma requisição caiu e você não sabe se ela passou, envie de novo com o
mesmo cabeçalho Idempotency-Key. O post não sai duas vezes e uma imagem não é cobrada duas vezes.
curl -X POST https://craftopen.space/api/v1/tools/schedule_post \
-H "Authorization: Bearer craft_your_key" \
-H "Idempotency-Key: post-2026-09-27-lime-1" \
-H "Content-Type: application/json" \
-d '{"account_ids": ["..."], "confirm_usernames": ["@lime_agency"],
"carousel_id": "...", "caption": "Post text",
"scheduled_at": "2026-09-27T19:00:00+03:00"}'
⚠️ As confirmações fazem parte da requisição. Onde o site perguntaria "tem certeza?",
a API espera uma confirmação nos parâmetros: os @ das contas num post
(confirm_usernames), o número exato de destinatários num disparo (confirm_recipients),
o nome de um funil ativo que você está editando, o preço de um bloco de pagamento. Se a
confirmação não bater com o que a Craft vê, nada é enviado — a resposta diz o
valor correto.
Erros e o que fazer#
| Status | Significado |
|---|---|
| 400 | Parâmetros inválidos — message diz quais |
| 401 | Sem chave, chave errada ou a chave foi revogada |
| 403 | Plano sem API (plan_required), a chave não tem uma permissão (scope_required), ou o modo de publicação não permite a ação |
| 404 | Não encontrado: funil, contato, post ou método |
| 409 | Os dados mudaram desde que você os leu, ou uma confirmação não bateu — leia de novo |
| 429 | Limite de requisições — espere tantos segundos quanto o cabeçalho Retry-After indica |
| 500, 503 | Falha temporária — tente de novo em um minuto com o mesmo Idempotency-Key |
Limites#
- 60 requisições por minuto e 10.000 por dia por conta — somando todas as chaves. O dia é contado no horário de Moscou (UTC+3). Precisa de mais? Escreva para o suporte; o limite é aumentado sem mudar de plano.
- Os webhooks não contam no limite.
- As imagens gastam créditos pelos mesmos preços do site, e nunca acima do limite diário que você definiu para a chave.
- Disparos: no máximo o número escolhido por dia por bot. Um teste para você com
send_broadcast_testexatamente do mesmo texto é obrigatório antes do envio.
Webhooks#
API e webhooks → Adicionar webhook: digite o endereço do seu servidor (só https://) e escolha os
eventos. Logo depois da criação, a Craft mostra o segredo de assinatura — guarde, ele não é mostrado de novo
(você pode emitir um novo com "Novo segredo").
Testar envia um evento ping e mostra o que o seu servidor respondeu. Registro lista as entregas
recentes: o que foi enviado, se chegou, a resposta e um botão "Tentar novamente".
Eventos#
| Evento | Quando chega |
|---|---|
contact.created |
Alguém se inscreveu num bot ou escreveu pela primeira vez no seu Direct do Instagram |
funnel.button_clicked |
Alguém clicou num botão de um funil |
funnel.goal_reached |
Alguém atingiu a meta do funil |
payment.succeeded |
Um pagamento passou por um bloco de pagamento do funil |
post.published |
Um post foi publicado na rede social |
agent.message_received |
A mensagem de um cliente chegou ao agente de IA — no Instagram ou no Telegram |
agent.replied |
O agente de IA respondeu ao cliente e a resposta foi enviada. Os dados têm o texto da resposta |
agent.handed_over |
O agente de IA passou o cliente para a equipe. Os dados têm o resumo e se foi entregue, e para quem |
Os eventos do agente trazem platform (instagram ou telegram), account_id (a conta do Instagram ou o bot), contact_id e um horário, para você poder guardar o histórico das conversas do agente no seu próprio CRM ou serviço.
Exemplo de corpo da requisição:
{
"id": "6f1c…",
"type": "contact.created",
"created_at": "2026-09-26T09:04:11+00:00",
"data": {
"platform": "telegram",
"contact_id": "…",
"bot_username": "shop_bot",
"first_name": "Anna",
"username": "anna",
"source": {"type": "link", "ref": "promo"}
}
}
O id do evento é o mesmo em todas as tentativas — use-o para descartar duplicatas.
Verificando que uma requisição veio da Craft#
Toda requisição tem o cabeçalho Craft-Signature: t=<time>,v1=<signature>. A assinatura é o
HMAC-SHA256 da string <time>.<request body> com o seu segredo. Calcule e compare:
import hmac, hashlib, time
def craft_signature_ok(header: str, body: bytes, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300: # older than 5 minutes — reject
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
const crypto = require("crypto");
function craftSignatureOk(header, rawBody, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
⚠️ A assinatura é calculada sobre o corpo bruto da requisição — exatamente os bytes que chegaram. Se o seu framework interpreta o JSON e o serializa de novo antes, a assinatura não vai bater.
Novas tentativas#
A Craft espera até 10 segundos por uma resposta. Qualquer resposta 2xx conta como entregue.
Senão, a Craft tenta de novo depois de 1 minuto, 5 minutos, 30 minutos, 2, 6, 12 e 24 horas — 8
tentativas no total, depois das quais o evento é marcado como "falhou" (você pode reenviá-lo pelo registro).
🔴 Depois de 50 entregas falhas seguidas, o webhook é desativado para não continuar batendo num endereço morto. Corrija o seu servidor e clique em "Ativar" — o contador zera. Os eventos que aconteceram enquanto o webhook estava desativado não são enviados.
Responda rápido e faça o trabalho demorado depois de responder: se o seu servidor levar mais de 10 segundos, a Craft conta a tentativa como falha e envia o evento de novo.
Seu próprio canal: respostas do agente de IA#
Se os clientes te escrevem onde a Craft não está conectada (seu próprio mensageiro, chat do site, CRM), o agente de IA também pode responder lá. Seu sistema envia a mensagem do cliente — a Craft devolve a resposta do agente. Seu sistema a entrega ao cliente.
curl -X POST https://craftopen.space/api/v1/agent/reply \
-H "Authorization: Bearer craft_…" -H "Content-Type: application/json" \
-d '{"ig_user_id": "1784…", "contact_id": "client-42", "text": "How much is JET+?", "name": "Ivan"}'
- De quem é o agente que responde —
ig_user_idde uma conta do Instagram outg_bot_idde um bot do Telegram com agente configurado. São usadas as regras, a base de conhecimento, o modelo e as configurações de transferência dele. contact_id— o id estável do seu cliente; o agente lembra a conversa por ele.name— opcional, para a transferência à equipe.- Resposta:
reply— texto para o cliente,handed_over— o agente passou o cliente para a equipe (o lead vai para onde vão os leads do Instagram),paused— o agente fica em silêncio até a equipe devolvê-lo,credits_charged— créditos gastos. - As respostas custam créditos, igual no Instagram. Sem créditos — você recebe o erro
no_credits. - Os eventos
agent.message_received,agent.repliedeagent.handed_overtambém disparam para esse canal.
⚠️ Por esse canal, o agente envia só texto — nada de vídeos ou arquivos dos funis.
Ainda não disponível#
- Bibliotecas de cliente prontas — use a descrição OpenAPI.
- Criar chaves e webhooks pela própria API — só na página API e webhooks.
- "Entrar com a Craft" para apps de terceiros: uma chave só dá acesso à sua própria conta.