Skip to content
EmbPay

Receiving webhooks and verifying signatures

Receive seven order and subscription events at your own https endpoint, verify the signature, and understand the retry schedule.

Add an endpoint in Settings and EmbPay will POST events to it as they happen. Webhooks are available on every plan.

The events

  • order.completed
  • order.refunded
  • order.failed
  • subscription.created
  • subscription.renewed
  • subscription.payment_failed
  • subscription.canceled

Verifying the signature

Every delivery carries a signature header. The value has two parts: a timestamp and a hex digest.

X-EmbPay-Signature: t=1757700000,v1=4f1d...c9a2

The digest is an HMAC-SHA256, keyed with your endpoint secret, over the timestamp and the raw request body joined by a full stop. Sign the exact bytes you received, before any JSON parsing, or the digest will not match.

const [tPart, v1Part] = header.split(",");
const timestamp = tPart.split("=")[1];
const signature = v1Part.split("=")[1];

const expected = crypto
  .createHmac("sha256", endpointSecret)
  .update(`${timestamp}.${rawBody}`)
  .digest("hex");

// Compare in constant time
const ok = crypto.timingSafeEqual(
  Buffer.from(expected),
  Buffer.from(signature)
);

Two other headers come with it: one naming the event and one carrying a unique delivery id, which is useful for making your handler idempotent.

Endpoint requirements

  • A public https URL. Credentials in the URL, localhost, and private or internal addresses are all rejected.
  • Up to five endpoints per account.
  • Respond within five seconds. Redirects are never followed, so return your status directly rather than redirecting.

Retries and the delivery log

A failed delivery is retried five times, after one minute, ten minutes, one hour, six hours and twenty-four hours. After the last attempt it is marked dead and left alone.

Each endpoint has a log in Settings showing status, event, attempt count, the HTTP code you returned and the timestamp, with a replay button on every row. Replaying resets the retry chain. Delivery history is kept for thirty days.

Still stuck?

Email support@embpay.com. It is the same address on every plan — there is no priority queue to be prioritised over. If something on this page disagrees with what the product does, that is a bug in this page and we want to hear about it.