Skip to content

Webhooks overview

A webhook is an HTTPS endpoint of yours that CardOffice calls when an event occurs: a photo is approved, an order ships, a card is revoked.

  1. Sign in as an administrator and open Settings → Integrations.
  2. Under Webhooks choose New webhook.
  3. Enter your endpoint URL and the events you want. The URL must be https:// and publicly reachable.
  4. Copy the signing secret. It is shown once, and you need it to verify signatures.

Each delivery is an HTTP POST with a JSON body:

{
"event": "order.status_changed",
"createdAt": "2027-02-01T03:00:00.412Z",
"companyId": "7e0d9c3a-2d8b-4e57-8f43-5c3a1b2d9e10",
"data": {
"orderId": "a3e8e6f0-1c7f-4a52-8f0e-3d4f6b1d5c77",
"orderNumber": "ACME-2027-0412",
"from": "draft",
"to": "cancelled"
}
}

and these headers:

Header Value
Content-Type application/json
User-Agent ID-Portal-Webhooks/2.0
X-IDPortal-Event The event name, for routing before you parse the body
X-IDPortal-Delivery A unique ID for this delivery. Use it to de-duplicate
X-IDPortal-Signature t=<unix seconds>,v1=<hmac>. See Verifying signatures

Reply with any 2xx status within a few seconds to acknowledge. Do your real work after responding, by queueing it. Any other status, or a timeout, counts as a failure.

Failed deliveries are retried with exponential backoff, starting at one minute and doubling to a ceiling of 30 minutes, for up to 8 attempts.

If an endpoint fails 20 times in a row, CardOffice disables the webhook so it stops hammering a broken receiver. Fix the endpoint and re-enable the webhook in Settings → Integrations. Every delivery, with the response status and the first part of the response body, is recorded for debugging.

Design your receiver for at-least-once delivery

Section titled “Design your receiver for at-least-once delivery”
  • De-duplicate on X-IDPortal-Delivery. A retry after a slow response can deliver the same event twice.
  • Do not rely on ordering. Two events close together can arrive out of order. Use createdAt, or fetch the current state from the API when it matters.
  • Treat the payload as a notification. Fetch the full object from the API when you need more than the fields supplied.

CardOffice only delivers to public addresses. It resolves your hostname at delivery time and refuses to connect to private, loopback or link-local addresses, which prevents a webhook being used to reach internal systems. If your receiver sits on a private network, put a public HTTPS endpoint in front of it.

© 2026 Secure ID Ltd. All rights reserved.Documentation licence and terms