Skip to main content
Webhooks deliver real-time notifications to your server when events occur in Closient. Each webhook endpoint receives signed HTTP POST requests with JSON payloads.

Creating a Webhook Endpoint

Configure endpoints in Settings > Integrations in your Dashboard, or via the Integrations API. Each endpoint has:
  • URL — your HTTPS endpoint (HTTPS required in production)
  • Event types — which events to subscribe to (e.g., ["offer.updated", "product.claimed"])
  • Filters — optional per-event-type filtering rules
  • Signing secret — auto-generated 64-byte hex secret for payload verification

Payload Format

{
  "event_id": "evt_abc123def456",
  "event_type": "product.updated",
  "timestamp": "2026-04-01T12:00:00Z",
  "data": {
    "id": "ack3p9tw6x7r",
    "gtin": "00012345678905",
    "changes": ["product_name", "description"]
  }
}

Verifying Signatures

Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature of the payload body.
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        payload,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)
Always verify the signature before processing a webhook payload. This prevents forged requests from being acted upon.

Secret Rotation

When you rotate a signing secret, the previous secret remains valid for a 24-hour grace period. During this window, verify against both the current and previous secrets to avoid rejecting legitimate deliveries.

Delivery Lifecycle

Each delivery progresses through these statuses:
StatusDescription
PENDINGQueued for delivery
DELIVEREDReceived 2xx response
FAILEDNon-2xx response or connection error
RATE_LIMITEDEndpoint is being rate-limited
DEAD_LETTERAll retry attempts exhausted

Retry Policy

Failed deliveries are retried with exponential backoff:
AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
After all retry attempts are exhausted, the delivery moves to DEAD_LETTER status. You can inspect dead-lettered deliveries in the Dashboard or via the API.

Best Practices

  • Return 2xx quickly — do heavy processing asynchronously after acknowledging receipt
  • Handle duplicates — use the event_id field for idempotency
  • Verify signatures — always validate X-Webhook-Signature before processing
  • Monitor delivery health — check for consecutive failures in the Dashboard
See the Integrations API reference for endpoint management and delivery inspection.