DocumentaçãoEnviar dados
API REST
Envie eventos de qualquer stack com POST /api/v1/events: envelope, autenticação, envio em lote e deduplicação idempotente.
Toda entrada de dados na Holdy converge em um endpoint HTTP. Se o SDK não cobre a sua stack, fale direto com ele.
Endpoint
POST https://holdy.chat/api/v1/events
Authorization: Bearer hol_live_...
Content-Type: application/json
Sucesso responde 202 com { ok, event_id, ingested_at }. Erros seguem RFC 7807 (problem+json) com status 400, 401 ou 500.
Envelope
| Campo | Tipo | Obrigatório | Semântica |
|---|---|---|---|
event | string | sim | Nome do evento, sem canonicalização ("invite_sent", "workflow.blocked"). |
occurred_at | ISO 8601 | — | Quando ocorreu no seu produto. Default: horário do servidor. Mande sempre que usar external_id: a deduplicação compara os dois. |
user_id | string ≤200 | — | ID do usuário final no seu produto. |
anonymous_id | string ≤200 | — | ID persistido no browser antes do login. |
properties | object | — | Propriedades livres do evento. Default {}. |
context | object | — | Metadata (página, device). Use context.account_external_id para associar a conta pela chave do seu produto. |
external_id | string ≤200 | — | ID do evento na origem, para deduplicação idempotente. |
Exemplo
curl -X POST https://holdy.chat/api/v1/events \
-H "Authorization: Bearer hol_live_..." \
-H "Content-Type: application/json" \
-d '{
"event": "invite_sent",
"occurred_at": "2026-10-05T14:32:00Z",
"user_id": "user_42",
"properties": { "plan": "pro" },
"context": { "account_external_id": "acme-inc" },
"external_id": "invite-8812"
}'
Envio em lote
POST /api/v1/events/bulk aceita um array de até 500 envelopes. A aceitação é parcial: eventos inválidos voltam em rejected com o índice, os demais entram. Reenviar o batch inteiro após uma falha é seguro.
Deduplicação
Envie external_id e occurred_at juntos: o mesmo evento reenviado com os dois iguais responde 202 com deduped: true em vez de duplicar, o que deixa retries e backfills seguros. Use o horário em que o evento aconteceu no seu produto, guardado junto do registro, e não o horário do envio.
Sem occurred_at, cada envio recebe o horário do servidor e o reenvio entra como evento novo, mesmo com o mesmo external_id. Eventos sem external_id nunca colidem entre si.
Identidade
Envie os IDs que você tem (user_id, anonymous_id, properties.email, context.account_external_id) e a Holdy resolve usuário e conta do lado dela. Você nunca precisa conhecer IDs internos da Holdy.
Lendo o que a Holdy encontrou
O que entra por eventos sai por oportunidades e sinais. Use a chave secreta (escopo behavior:read) para levar o resultado pro seu CRM, planilha ou job — a organização vem da chave, nunca do parâmetro.
curl https://holdy.chat/api/v1/opportunities?status=open \
-H "Authorization: Bearer hol_live_..."
Aceita status, since (ISO 8601), limit (até 200) e cursor. A resposta traz next_cursor enquanto houver página seguinte — o cursor é keyset sobre data e id, então nenhuma linha se perde entre páginas mesmo com registros criados no mesmo instante.
GET /api/v1/signals segue as mesmas regras e aceita ainda type e severity. Sinal é mudança e expira: cada um traz expires_at, e por padrão só vêm os ativos. Sinal com advisory: true informa e nunca vira oportunidade.
Toda oportunidade e todo sinal trazem evidence_ref. Para abrir a prova por trás do achado, chame GET /api/v1/evidence/opportunity/{id} — a resposta resolve as referências em evidência completa.