Skip to content

API & Security

CertSeal Webhooks

Get notified in real time when certificates are issued, sent, fail to send, or are viewed. Deliveries are signed and retried.

Last updated: June 18, 2026

Webhooks push certificate events to your endpoint as they happen, so you can update systems, notify your team, or trigger downstream automation without polling. Subscriptions are managed through the REST API, and the same events power our Zapier and Make.com apps.

Events

EventFires when
certificate.issuedA recipient is created (API, bulk, or CSV import).
certificate.sentA certificate email is successfully sent.
certificate.failedA certificate email fails to send (payload includes an error).
certificate.viewedA recipient opens their certificate for the first time (payload includes viewer details).

Creating a subscription

Register an endpoint and the events you want with the REST API:

curl -X POST \
  https://services.certseal.com/api/v1/webhooks/subscriptions \
  -H "Authorization: Bearer $CERTSEAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/certseal",
    "events": ["certificate.issued", "certificate.sent"]
  }'

The response includes a signing secret (prefixed wh_sec_) shown once — store it to verify deliveries. Your endpoint URL must be HTTPS in production. A workspace can have up to 20 subscriptions.

To send yourself a sample delivery, call POST /webhooks/subscriptions/{id}/test. You can rotate the secret with POST /webhooks/subscriptions/{id}/rotate-secret.

Delivery format

CertSeal sends an HTTP POST with a JSON envelope:

{
  "id": "whe_AbC123...",
  "type": "certificate.issued",
  "createdAt": "2026-05-01T00:00:00.000Z",
  "data": {
    "id": "rec_...",
    "batchId": "batch_...",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "certificateId": "CERT-2026-003843-000001",
    "shareToken": "…",
    "certUrl": "https://services.certseal.com/v/…",
    "issueDate": "2026-05-01T00:00:00.000Z",
    "expiryDate": null,
    "data": { "score": "94%" },
    "emailStatus": "sent",
    "emailSentAt": "2026-05-01T00:01:00.000Z",
    "createdAt": "2026-05-01T00:00:00.000Z"
  }
}

For certificate.failed, data also includes an error string. For certificate.viewed, data also includes a viewer object (viewedAt, userAgent, referer, ip).

Every delivery includes these headers:

HeaderValue
X-CertSeal-EventThe event type, e.g. certificate.issued.
X-CertSeal-DeliveryA unique delivery ID — use it as an idempotency key.
X-CertSeal-Signaturet=<unix>,v1=<hmac> — see below.
X-CertSeal-TimestampUnix seconds, matching t in the signature.
User-AgentCertSeal-Webhook/1

Verifying signatures

Each request is signed with HMAC-SHA256 using your subscription’s signing secret. The X-CertSeal-Signature header has the form t=<timestamp>,v1=<hex>, where the HMAC is computed over the string `${t}.${rawRequestBody}`.

To verify: recompute the HMAC with your secret and compare it to v1 using a constant-time comparison, and reject requests where the timestamp is more than ~5 minutes from now (to prevent replay).

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (Math.abs(Date.now() / 1000 - t) > 300) return false; // replay window
  const expected = createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Verify against the raw request body, before any JSON parsing reformats it.

Retries and delivery

  • Deliveries are at-least-once — the same delivery may arrive more than once. Deduplicate on X-CertSeal-Delivery.
  • A delivery succeeds on any 2xx response. Non-2xx responses and timeouts are retried with increasing backoff (1m → 5m → 30m → 2h → 12h → 24h) for up to 7 attempts before the delivery is marked failed.
  • Respond quickly (within ~10 seconds) — do heavy work asynchronously after acknowledging.
  • Return 410 Gone to have CertSeal unsubscribe the endpoint automatically.

Support

Questions about webhooks? Email support@certseal.com — we typically reply within 1 business day (Monday–Friday, 9:00 AM–6:00 PM SGT). See the support guide for all contact options.