Ir para o conteúdo

Endpoints

Webhooks

Subscribe a URL to workspace events. This is what the Make instant triggers call when a scenario is turned on and off.

Como os webhooks funcionam

Os webhooks enviam um evento para a sua URL quando algo acontece no workspace: um novo contato, um agendamento, um pedido pago, uma chamada concluída. Cada entrega é assinada, para você conferir que veio do Entagl.

Configure um endpoint

Crie um endpoint com POST /webhooks. Escolha os tipos de evento na lista abaixo (ou em GET /events), ou use um curinga como contact.* ou *. A resposta inclui o secret de assinatura uma única vez: guarde-o. O app do Entagl para o Make faz isso por você quando um scenario com um trigger do Entagl é ativado, e exclui o endpoint quando ele é desativado.

Requisição
curl -X POST "https://api.entagl.com/api/v1/webhooks" \
  -H "Authorization: Bearer ai_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/entagl/webhooks",
    "events": ["contact.created", "booking.*"],
    "description": "CRM sync"
  }'

O webhook que você configura na página Canais → Webhooks do app usa o formato original: o corpo é { event, workspace_id, occurred_at, data } e X-Entagl-Signature é sha256= seguido de um HMAC-SHA256 do corpo bruto. Tudo o que vem abaixo descreve endpoints criados pela API.

Formato do evento

Cada entrega é um POST com um evento JSON. type diz o que aconteceu e data traz os detalhes desse tipo (veja a lista de eventos). actor diz quem causou o evento (ai, human, customer, system, api, import ou provider) e source.connection_id diz qual credencial, para que uma integração possa ignorar as próprias mudanças. Os eventos de atualização também trazem changes com os nomes dos campos alterados.

contact.created
{
  "id": "evt_5c1f0a9e7b2d4e3f8a6c0b1d2e3f4a5b",
  "object": "event",
  "type": "contact.created",
  "api_version": "2026-10-01",
  "occurred_at": "2026-10-01T14:32:11.482Z",
  "created_at": "2026-10-01T14:32:11.482Z",
  "workspace_id": "00000000-0000-0000-0000-000000000000",
  "actor": {
    "type": "api",
    "id": "user_9f2c1a"
  },
  "resource": {
    "type": "contact",
    "id": "6789"
  },
  "source": {
    "connection_id": "apikey:42",
    "via": "api"
  },
  "data": {
    "contact_id": 6789,
    "name": "Jane Doe",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": "+15551234567",
    "email": "jane@example.com",
    "channel": "instagram",
    "tags": [
      "vip",
      "botox"
    ],
    "stage": {
      "funnel_id": 3,
      "stage_id": 14,
      "stage_name": "Qualified"
    },
    "assigned_to_user_id": "user_9f2c1a",
    "language": "en",
    "custom_fields": {
      "budget": "500-1000",
      "preferred_branch": "Downtown"
    },
    "created_at": "2026-09-28T10:02:44.000Z",
    "updated_at": "2026-10-01T14:32:11.482Z"
  },
  "changes": null
}
  • Content-Typeapplication/json
  • User-AgentEntagl-Webhooks/2.0
  • X-Entagl-SignatureAssinatura, veja abaixo.
  • X-Entagl-Event-IdO ID do evento. Use para ignorar duplicatas.
  • X-Entagl-Event-TypeO tipo do evento, ex.: contact.created.
  • X-Entagl-Delivery-Attempt1 na primeira tentativa, depois 2, 3 …

Verifique a assinatura

O header X-Entagl-Signature tem este formato: t=1767225600,v1=5257a869…. t é o horário de envio em segundos Unix. Cada v1 é um HMAC-SHA256, em hexadecimal, do texto {t}.{raw body} gerado com o secret do seu endpoint. Calcule você mesmo e compare em tempo constante. Rejeite a requisição quando t estiver a mais de 5 minutos do seu relógio. Depois de uma rotação de secret, há dois valores v1 por 24 horas: aceite a requisição se qualquer um deles bater.

Node.js (Express)
import crypto from 'node:crypto';
import express from 'express';

const app = express();
// The secret returned once by POST /api/v1/webhooks (or by rotate-secret).
const SECRET = process.env.ENTAGL_WEBHOOK_SECRET;

// Read the RAW body: the signature covers the exact bytes Entagl sent.
app.post('/entagl/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  const rawBody = req.body.toString('utf8');
  if (!verifyEntaglSignature(req.get('X-Entagl-Signature') || '', rawBody, SECRET)) {
    return res.status(400).send('invalid signature');
  }
  const event = JSON.parse(rawBody);
  // Deliveries can repeat: skip an event.id you have already handled.
  console.log(event.type, event.id);
  res.sendStatus(200); // any 2xx within 10 seconds counts as delivered
});

function verifyEntaglSignature(header, rawBody, secret, toleranceSeconds = 300) {
  const parts = header.split(',').map((p) => p.trim());
  const t = Number(parts.find((p) => p.startsWith('t='))?.slice(2));
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  return parts
    .filter((p) => p.startsWith('v1='))
    .some((p) => {
      const got = p.slice(3);
      return got.length === expected.length &&
        crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
    });
}

app.listen(3000);

Entrega e novas tentativas

  • Responda com qualquer status 2xx em até 10 segundos. Redirecionamentos não são seguidos.
  • Qualquer outra resposta é uma tentativa falha. O Entagl tenta de novo após 30 segundos, 2 minutos, 10 minutos, 1 hora, 6 horas e 24 horas, e então marca a entrega como falha (7 tentativas no total).
  • 410 Gone interrompe as tentativas na hora e desativa o endpoint.
  • Um endpoint que continua falhando por 72 horas é desativado e o proprietário do workspace é avisado. Reative-o com PATCH /webhooks/:id e "status": "active".
  • Uma entrega pode chegar mais de uma vez, e os eventos podem chegar fora de ordem. Use o ID do evento para ignorar duplicatas.
  • GET /webhooks/:id/deliveries mostra os últimos 30 dias de tentativas; POST …/redeliver envia uma de novo.

Privacidade

Por padrão, os eventos deixam de fora o que os clientes escreveram (texto das mensagens, transcrições, resumos, notas) e os dados de contato deles (nomes, telefones, e-mails, nomes de usuário). A lista de eventos mostra esses campos para cada evento. Para recebê-los, defina include_content e/ou include_contact_details no endpoint. Só o proprietário ou um admin do workspace pode ativá-los. Em workspaces HIPAA, eles nunca são enviados, seja qual for a configuração. Quando um campo privado é omitido, changes ainda lista o nome dele, mas nunca o valor antigo.

Lista de eventos

Todos os tipos de evento que o Entagl envia hoje. message.received e message.sent têm alto volume: um curinga nunca os inclui, então liste-os pelo nome. GET /events retorna o mesmo catálogo em JSON.

Contacts (11)

contact.createdContact created

Fires when a new contact is added: a first message from someone new, a manual add, an import or the API.

Campos de dados de contato:namefirst_namelast_namephoneemailcustom_fields

contact.updatedContact updated

Fires when any contact field or custom field changes. The envelope "changes" lists the changed fields and their previous values.

Campos de dados de contato:namefirst_namelast_namephoneemailcustom_fields

contact.deletedContact deleted

Fires when a contact is deleted. Carries ids only.

contact.tag_addedContact tag added

Fires when one or more tags are added to a contact.

contact.tag_removedContact tag removed

Fires when one or more tags are removed from a contact.

contact.stage_changedLifecycle stage changed

Fires when a contact moves to another funnel stage, or the stage is removed.

contact.assignedContact owner changed

Fires when a contact is assigned to a team member or unassigned.

contact.lead_capturedLead captured

Fires when the AI (or a form) marks a contact as a lead, with a short summary of what they want.

Campos de conteúdo:summary

Campos de dados de contato:namephoneemail

contact.mergedContacts merged

Fires when two contacts are merged into one. The secondary contact id now redirects to the primary.

contact.opted_outContact opted out

Fires when a contact is marked do-not-contact or opts out of marketing messages.

note.createdContact note added

Fires when a team member adds a note to a contact.

Campos de conteúdo:body

Conversations (7)

conversation.createdConversation opened

Fires when a new conversation starts on any channel.

conversation.reopenedConversation reopened

Fires when a closed conversation is opened again, by a new customer message or a team member.

conversation.closedConversation closed

Fires when a conversation is closed by a team member, the API or auto-close, with the closing note if any.

Campos de conteúdo:closing_note_text

conversation.assignedConversation assignee changed

Fires when a conversation is assigned to a team member or unassigned.

conversation.ai_pausedAI paused on a conversation

Fires when AI replies are paused on a conversation (team member takeover, handover, spam, schedule or API).

conversation.ai_resumedAI resumed on a conversation

Fires when AI replies are switched back on for a conversation.

conversation.comment_createdConversation comment added

Fires when a team member (or the API) adds an internal comment to a conversation. Customers never see comments.

Campos de conteúdo:body

Messages (3)

message.receivedIncoming message
Alto volume: assine pelo nome

Fires for every message a customer sends, on any channel. High volume — subscribe only if you need every message.

Campos de conteúdo:text

message.sentOutgoing message
Alto volume: assine pelo nome

Fires for every message sent to a customer: AI replies, team replies, campaigns and automations.

Campos de conteúdo:text

message.send_failedMessage failed to send

Fires when a message to a customer could not be delivered by the channel.

Handovers (2)

handover.requestedHandover requested

Fires when the AI hands a conversation to a human (customer asked for a person, complaint, or a question it could not answer).

Campos de conteúdo:summary

Campos de dados de contato:customer_namecustomer_phone

handover.resolvedHandover resolved

Fires when a team member (or auto-resolve) marks a handover as handled.

AI (3)

conversation.followup_sentFollow-up sent

Fires when the AI sends an automatic follow-up to a customer who went quiet.

ai_turn.failedAI reply failed

Fires when the AI could not produce a reply for a customer message (a fallback message may have been sent instead).

message_feedback.submittedAI reply rated

Fires when a team member gives thumbs up or down to an AI reply.

Campos de conteúdo:comment

Bookings (6)

booking.createdBooking created

Fires when an appointment is created for a customer.

Campos de conteúdo:conversation_summarydocuments

Campos de dados de contato:customer_namecustomer_phone

booking.documents.addedBooking documents added

Fires when a customer shares a document or photo in a conversation after their booking was created. Delivers only the new file(s).

Campos de conteúdo:documents

Campos de dados de contato:customer_namecustomer_phone

booking.updatedBooking updated

Fires when any booking detail changes (time, service, duration, location, notes). The envelope "changes" lists what changed.

Campos de dados de contato:customer_namecustomer_phone

booking.rescheduledBooking rescheduled

Fires when a booking moves to a new date or time.

Campos de dados de contato:customer_namecustomer_phone

booking.cancelledBooking cancelled

Fires when a booking is cancelled by the customer (through the AI), a team member, or the API.

Campos de dados de contato:customer_namecustomer_phone

booking.status_changedBooking status changed

Fires when a booking status changes, e.g. confirmed, completed or no-show.

Campos de dados de contato:customer_namecustomer_phone

Reminders (4)

reminder.createdReminder created

Fires when a reminder is created.

Campos de conteúdo:titlenote

reminder.firedReminder due

Fires when a reminder becomes due and the assignees are notified.

Campos de conteúdo:titlenote

reminder.closedReminder closed

Fires when a reminder is marked done.

Campos de conteúdo:titlenote

appointment_reminder.sentAppointment reminder sent

Fires when an automatic appointment reminder (WhatsApp template or SMS) is sent to a customer.

Orders (6)

order.createdOrder created

Fires when an order is created by the AI, a team member, a store sync or the API.

Campos de dados de contato:customer_namecustomer_phone

order.updatedOrder updated

Fires when any order detail or item changes. The envelope "changes" lists what changed.

Campos de dados de contato:customer_namecustomer_phone

order.status_changedOrder status changed

Fires when an order status changes (for example confirmed, shipped, delivered).

Campos de dados de contato:customer_namecustomer_phone

order.paidOrder paid

Fires when an order is marked as paid.

Campos de dados de contato:customer_namecustomer_phone

order.cancelledOrder cancelled

Fires when an order is cancelled.

Campos de dados de contato:customer_namecustomer_phone

order.payment_proof_uploadedPayment proof uploaded

Fires when a customer (through the AI) or a team member attaches a payment receipt to an order.

Products (3)

product.createdProduct created

Fires when a product is added to the catalog.

product.updatedProduct updated

Fires when a product changes (price, stock, details).

product.deletedProduct deleted

Fires when a product is removed from the catalog.

Calls (3)

call.endedCall ended

Fires after every AI phone or WhatsApp call, with outcome and (opt-in) summary and transcript.

Campos de conteúdo:summarytranscript

Campos de dados de contato:from_numberto_number

call.missedMissed call

Fires when an incoming call was not answered or an outgoing call got no answer.

Campos de conteúdo:summarytranscript

Campos de dados de contato:from_numberto_number

call.voicemail_receivedVoicemail received

Fires when a caller leaves a voicemail.

Campos de conteúdo:transcript_text

Campos de dados de contato:from_number

Campaigns (3)

campaign.completedCampaign finished sending

Fires when a broadcast campaign finished sending to all recipients.

campaign_recipient.repliedCampaign reply

Fires when a recipient replies to a campaign message.

campaign_recipient.failedCampaign message failed

Fires when a campaign message could not be delivered to a recipient.

Forms (1)

form.submittedForm submitted

Fires when a customer submits a form (website widget, hosted link or in-chat intake).

Campos de conteúdo:fields

Account (3)

channel.disconnectedChannel disconnected

Fires when a channel stops working (token expired, access removed) or is disconnected.

channel.reconnectedChannel healthy again

Fires when a previously failing channel works again.

credits.threshold_reachedCredits running low

Fires when credit usage crosses 80%, 100% or 120% of the plan allowance.

Workspace (3)

tag.createdTag created

Fires when a tag is added to the workspace tag list.

tag.updatedTag updated

Fires when a workspace tag is renamed or recolored.

tag.deletedTag deleted

Fires when a workspace tag is deleted (it is removed from every contact).

Os caminhos são relativos à URL base. Cada card lista a permissão que a chamada exige e todos os parâmetros, com tipo e limites.

GET
/webhooks

List webhook endpoints.

Permissão: integrations
Paginado
POST
/webhooks

Create a webhook endpoint. The signing secret is returned once, in this response.

Permissão: integrations

Corpo JSON

  • urlobrigatóriostring (URL)

    https:// URL that receives events, up to 2,048 characters. Private and internal addresses are refused (422 unsafe_url).

  • eventsobrigatórioarray of strings

    1–100 event types from GET /events, "<prefix>.*" (e.g. "contact.*") or "*". Wildcards never include message.received and message.sent; list those explicitly.

  • descriptionopcionalstring

    Up to 200 characters.

  • filtersopcionalobject

    Optional narrowing: channels (array of channel names, up to 20), actor_types (array, up to 7), sources (object of event type → source keys), ignore_own_changes (boolean — skip events caused by this same connection; on by default for connector-created endpoints).

  • include_contentopcionalboolean

    Include message text, transcripts and notes. Owner or admin only; refused on HIPAA workspaces.

  • include_contact_detailsopcionalboolean

    Include names, phones, emails and handles. Owner or admin only; refused on HIPAA workspaces.

  • created_viaopcionalenum

    Which tool created the endpoint.

    Valores permitidos:apimakezapiern8n

  • A workspace can have up to 100 endpoints (409 endpoint_limit_reached).
GET
/webhooks/:id

Retrieve a webhook endpoint with its status and last delivery result.

Permissão: integrations

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID (starts with "we_").

PATCH
/webhooks/:id

Update an endpoint, or pause and re-activate it.

Permissão: integrations

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID.

Corpo JSON

  • urlopcionalstring (URL)

    New receiving URL.

  • eventsopcionalarray of strings

    New event list.

  • descriptionopcionalstring | null

    Up to 200 characters.

  • filtersopcionalobject

    Optional narrowing: channels (array of channel names, up to 20), actor_types (array, up to 7), sources (object of event type → source keys), ignore_own_changes (boolean — skip events caused by this same connection; on by default for connector-created endpoints).

  • include_contentopcionalboolean

    Owner or admin only to turn on.

  • include_contact_detailsopcionalboolean

    Owner or admin only to turn on.

  • statusopcionalenum

    Re-activating resets the failure count.

    Valores permitidos:activepaused

  • On an endpoint that includes content or contact details, only an owner or admin can change url, events or filters.
DELETE
/webhooks/:id

Delete an endpoint (a Make trigger calls this when its scenario is turned off).

Permissão: integrations

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID.

POST
/webhooks/:id/rotate-secret

Issue a new signing secret. The previous secret keeps signing deliveries for 24 hours.

Permissão: integrations

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID.

POST
/webhooks/:id/test

Send a signed sample event to the endpoint now and return the result (delivered, status, error, duration_ms).

Permissão: integrations

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID.

Corpo JSON

  • eventopcionalstring

    Event type to sample. Defaults to the endpoint's first non-wildcard event, else a generic "webhook.test" event.

GET
/webhooks/:id/deliveries

Recent delivery attempts, newest first. Deliveries are kept for 30 days.

Permissão: integrations
Paginado

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID.

POST
/webhooks/:id/deliveries/:deliveryId/redeliver

Queue a delivery to be sent again. Answers 202.

Permissão: integrations

Parâmetros de caminho

  • idobrigatóriostring

    Endpoint ID.

  • deliveryIdobrigatóriointeger

    Delivery ID from the deliveries list.