A webhook is an HTTP request that Dintero sends to a URL you control whenever a subscribed event happens, such as a transaction being authorized or a settlement being created. Instead of polling the API for changes, your server receives the event data as soon as the event occurs.
Webhooks are configured per account and can deliver many event types. For events tied to a single Checkout session, you can also use the session callback_url. See Validating callbacks for that flow.
The checkout_authorization event delivers the same payload as the session callback_url. Use a webhook subscription when you want account-wide delivery instead of configuring a callback_url on every session.
Set up webhooks via API
Create a subscription with POST /accounts/{aid}/hooks/subscriptions. In the request you define:
config.url — the public HTTPS URL that receives the event payloads
events — the list of event types to subscribe to
config.secret — an optional secret used to sign deliveries (see Verify event signature)
When you create a subscription, Dintero sends a ping event so you can confirm the endpoint is set up correctly.
For the full list of event types and the payload of each, see the Webhooks API reference.
Set up webhooks via Backoffice
In Dintero Backoffice, go to Settings → Webhooks to create and manage subscriptions without using the API.
Verify event signature
To confirm that a request originated from Dintero, create the subscription with an HMAC-SHA1 secret. Each delivery then includes an event-signature header containing the HMAC-SHA1 digest of the request body, computed with your secret.
The webhook subscription API signs deliveries with HMAC-SHA1. This is separate from the Checkout callback_url signature, which uses HMAC-SHA256. See Validating callbacks.
Compute the digest over the raw request body and compare it to the header value:
const crypto = require("node:crypto");
// `rawBody` must be the exact bytes received, not a re-serialized object.
// In Express, capture them with the json parser's `verify` hook:
// express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } })
const verifyEventSignature = (rawBody, secret, eventSignature) => {
if (typeof eventSignature !== "string") {
return false;
}
const calculatedEventSignature = crypto
.createHmac("sha1", Buffer.from(secret))
.update(rawBody)
.digest("hex");
const received = Buffer.from(eventSignature, "hex");
const calculated = Buffer.from(calculatedEventSignature, "hex");
return (
received.length === calculated.length &&
crypto.timingSafeEqual(received, calculated)
);
};
Verify the signature against the raw request body bytes, exactly as received. Re-serializing the parsed JSON (for example with JSON.stringify(req.body)) can change whitespace or key order, producing a digest that does not match and rejecting legitimate deliveries.
Decode both hex signatures to buffers and compare them with a constant-time function such as crypto.timingSafeEqual rather than ===, so the check does not leak timing information. Guard against a missing header and unequal lengths first, since timingSafeEqual throws when the buffers differ in length.