← Guides

Setup Webhooks

Receive real-time HTTP notifications when events happen in the CRM — no polling required.

Prerequisites

  • An administrator user in the CRM: webhooks are created on the CRM screen, not through the API with a Service Account
  • A publicly accessible HTTPS endpoint to receive events

Step 1: Choose the events

The events are listed in Available Events. With a Service Account token you can also read the list your account accepts:

cURL
curl https://minha-empresa.platform-api.magnetcustomer.com/api/webhooks/triggers \
  -H "Authorization: Bearer YOUR_TOKEN"
Response 200
[
  {
    "_id": "Oportunidades",
    "triggers": [
      { "key": "deal.created", "label": "Oportunidade criada", "group": "deal", "groupName": "Oportunidades" },
      { "key": "deal.won", "label": "Oportunidade ganha", "group": "deal", "groupName": "Oportunidades" }
    ]
  }
]

Step 2: Create the webhook in the CRM

  1. As an administrator, open Integrations › Webhooks and create a new webhook.
  2. Give it a title, the URL of your endpoint and the events it should receive.
  3. Choose HMAC authentication and set a secret. Your endpoint uses the same secret to validate each delivery.

Step 3: Validate HMAC signature

Each webhook delivery includes an X-Webhook-Signature header. Always verify it to prevent spoofing:

Express.js
import crypto from 'crypto';

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = `sha256=${crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex')}`;

  const sigBuffer = Buffer.from(signature ?? '', 'utf8');
  const expBuffer = Buffer.from(expected, 'utf8');

  if (sigBuffer.length !== expBuffer.length) return false;

  return crypto.timingSafeEqual(sigBuffer, expBuffer);
}

app.post('/webhooks/crm', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-webhook-signature'] as string;
  const valid = verifyWebhookSignature(req.body.toString(), sig, process.env.WEBHOOK_SECRET!);

  if (!valid) return res.status(401).json({ error: 'Invalid signature' });

  const event = JSON.parse(req.body.toString());
  console.log('Event received:', event.event);

  res.json({ received: true });
});

Step 4: Acknowledge fast

Answer with a 2xx status as soon as the signature is valid and do the heavy work afterwards. Deliveries that fail or time out are retried: see the retry policy. The content of data depends on the event: log the body of the first deliveries while you build the integration.