Webhooks

Overview

Webhooks provide a way for the API Gateway to notify your application when specific events occur. Instead of polling the API for changes, your application receives HTTP POST requests with event data in real-time.

Key Concepts

ConceptDescription
WebhookA configuration that specifies which events to receive and where to send them
Event TypeThe category of event (e.g., SALE.CREATE, TRANSACTION.UPDATE)
Endpoint URLYour HTTPS URL that receives webhook notifications
SecretA shared key used to sign and verify webhook requests
Max ConcurrencyMaximum simultaneous webhook deliveries to your endpoint

Managing Webhooks

Before creating a webhook, you can retrieve the list of available event types you can subscribe to using the /v1/webhooks/events endpoint. Then create a new webhook configuration to start receiving notifications. One webhook configuration can receive notifications for multiple event types, if notifications should be sent to different urls then multiple webhook configurations need to be created.

Creating a webhook configuration

Endpoint: POST /v1/webhooks

Request Body

{
  "url": "https://api.example.com/webhooks/notifications",
  "storeId": "s_1234abcd",
  "eventTypes": ["SALE.CREATE", "SALE.UPDATE", "TRANSACTION.CREATE"],
  "maxConcurrency": 10,
  "secret": "your-secret"
}

Request Fields

FieldTypeRequiredDescription
urlstringYesThe HTTPS endpoint URL where webhooks will be delivered. Must be publicly accessible.
storeIdstringNoOptional store filter. If set, only events for this specific store are delivered. If null, events for all stores are delivered.
eventTypesstring[]YesList of event type codes to subscribe to. Use codes from the /v1/webhooks/events endpoint.
maxConcurrencyintegerYesMaximum number of concurrent webhook deliveries (1-100). Higher values allow faster delivery during high-volume periods but increase load on your endpoint.
secretstringYesThe secret key used to sign webhook requests. Minimum 8 characters, maximum 32 characters. Store this securely—you'll need it to verify signatures.

Response

HTTP Status: 201 Created

{
  "id": "es_1234abcd5678efgh",
  "url": "https://api.example.com/webhooks/notifications",
  "storeId": "s_1234abcd",
  "eventTypes": ["SALE.CREATE", "SALE.UPDATE", "TRANSACTION.CREATE"],
  "maxConcurrency": 10,
  "secret": "your-secure-webhook-secret-min-8-chars",
  "status": "Active",
  "createdAt": "2026-02-23T10:30:00Z",
  "_links": {
    "self": {
      "href": "/v1/webhooks/es_1234abcd5678efgh",
      "method": "GET"
    },
    "update": {
      "href": "/v1/webhooks/es_1234abcd5678efgh",
      "method": "POST"
    }
  }
}

Receiving Webhooks

When an event occurs for which there is an active webhook configuration, an HTTP POST request will be sent to your configured endpoint.

Webhook Payload Format

Request Headers:

Content-Type: application/json
Content-Digest: sha-256=:BASE64_HASH:
Signature-Input: sig=("host" "content-digest" "@request-target");alg="hmac-sha256";created=TIMESTAMP;nonce="NONCE"
Signature: sig=:BASE64_SIGNATURE:
Idempotency-Key: 7110eda4d09e062aa5e4a390b0a572ac0d2c0220
Buck-Event-Type: SALE.CREATE

Request Body:

The body contains application-specific JSON data for the event. The exact format depends on the event type. For example, for the SALE.CREATE event the content is identical to the GET /v1/sales/{id} response.

Signature Verification

For the notification signature we’ll be using the HTTP Message Signing standard. See https://datatracker.ietf.org/doc/html/rfc9421 & https://httpsig.org/.

Understanding the Signature Headers

HeaderDescription
Content-DigestSHA-256 hash of the request body, formatted as sha-256=:BASE64_HASH:
Signature-InputDescribes how the signature was constructed, including algorithm, timestamp, and nonce
SignatureThe actual HMAC-SHA256 signature, formatted as sig=:BASE64_SIGNATURE:

Example Headers:

Content-Digest: sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
Signature-Input: sig=("host" "content-digest" "@request-target");alg="hmac-sha256";created=1708689045;nonce="550e8400-e29b-41d4-a716-446655440000"
Signature: sig=:JsxlPZ9DJPdJZTBOz8qVOgP3VtFwSIRYVjNqLB3xVxE=:

Verification Steps

Step 1: Verify the content digest

Compute the SHA-256 hash of the request body and compare it to the Content-Digest header.

Step 2: Parse the Signature-Input header

Extract these components:

  • Signed components: "host", "content-digest", "@request-target"
  • Algorithm: hmac-sha256
  • Created timestamp: Unix timestamp when the signature was created
  • Nonce: Unique identifier for replay protection

Step 3: Build the signature base string

The signature base is a newline-separated string with this exact format:

"host": api.example.com
"content-digest": sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:
"@request-target": /webhooks/notifications
"@signature-params": ("host" "content-digest" "@request-target");alg="hmac-sha256";created=1708689045;nonce="550e8400-e29b-41d4-a716-446655440000"

Step 4: Compute the HMAC-SHA256

Using your webhook's secret as the key:

  1. Create HMAC-SHA256 with the secret
  2. Update with the signature base string (UTF-8 encoded)
  3. Compute the digest and base64-encode it

Step 5: Compare signatures

Extract the signature from the Signature header (between : delimiters) and compare with your computed value using a timing-safe comparison.

Step 6: Validate timestamp (recommended)

Check that the created timestamp is recent (within 5 minutes) to prevent replay attacks.


Delivery & Retry Behavior

Successful Delivery

A webhook is considered successfully delivered when your endpoint returns an HTTP status code in the 2xx range (200-299).

Retry Logic

If delivery fails (non-2xx response, timeout, or network error), the notification is retried:

  • Maximum retries: 10 attempts
  • Timeout: 20 seconds per request
  • Final status: After 10 failed attempts, the notification is marked as Failed

Response Requirements

Your webhook endpoint should:

  1. Return a 2xx status code on success (200, 201, 202, etc.)
  2. Respond within 20 seconds
  3. Be idempotent—you may receive the same webhook multiple times even if a success response was returned, since it could get lost on the return trip

Security Considerations

Secret Management

  • Use a strong secret (minimum 8 characters, max 32 characters)
  • Store the secret securely (e.g., environment variables, secret manager)

Endpoint Security

  • Always use HTTPS for your webhook endpoint
  • Verify signatures on every request before processing
  • Validate timestamps to prevent replay attacks (accept signatures no older than 5 minutes)

Idempotency

Design your webhook handler to be idempotent. Due to retries and at-least-once delivery semantics, you may receive the same notification multiple times. Every notification will have an Idempotency-Key to allow for easy deduplication.


Troubleshooting

Common Issues

IssuePossible CauseSolution
Signature verification failsWrong secret, modified payload, or header parsingDouble-check secret value and signature base format
Webhooks not receivedSubscription inactive or wrong event typesVerify subscription status and event type configuration
Duplicate notificationsRetries due to timeout/errorImplement idempotent handling