Skip to main content
On this page
Updated 1 min read

Integrating Webhooks

Integrating Webhooks

Adapto CMS webhooks send a signed HTTP POST to a URL you control whenever triggered from the backoffice. Use them to notify external systems — revalidation endpoints, Slack bots, build triggers, data pipelines — on demand.


Configuration

In the backoffice, go to Developer Tools → Webhooks and create a new webhook with:

  • Label — an internal name for identifying the webhook
  • URL — the HTTPS endpoint that will receive the POST

A signing secret is generated automatically on creation. It is shown once — copy and store it securely. The backoffice displays only a truncated version thereafter, with a copy button for the full value.


Delivery

Every delivery is an HTTP POST with Content-Type: application/json and the following body:

{
  "event_type": "manual",
  "tenant_id": "your-project-uuid",
  "timestamp": "2024-01-15T12:00:00",
  "data": {
    "environment": "production",
    "triggered_by": "deployment-script"
  }
}

data contains the key-value pairs entered in the trigger dialog.


Signature verification

Each delivery includes an adapto-signature header containing an HMAC-SHA256 signature of the raw request body, formatted as sha256={hex_digest}. Verify it on your receiving server before processing the payload:

import crypto from 'crypto';

function verifyAdaptoSignature(
  rawBody: string,
  secret: string,
  signatureHeader: string,
): boolean {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expected),
  );
}

// Express example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['adapto-signature'] as string;
  if (!verifyAdaptoSignature(req.body.toString(), process.env.WEBHOOK_SECRET!, signature)) {
    return res.status(401).send('Invalid signature');
  }
  const payload = JSON.parse(req.body.toString());
  // handle payload.data ...
  res.sendStatus(200);
});

Use express.raw() (or your framework's equivalent) to access the raw bytes before any JSON parsing — the HMAC is computed over the exact bytes sent, so parsing and re-serializing first will produce a different digest.


Triggering

From the webhook list, use the Trigger button to fire a delivery immediately. The trigger dialog accepts an optional payload of typed key-value pairs (string, number, or boolean) that populate the data field in the request body.