Apiable

Automation

Webhooks

Configure an outbound webhook in Apiable: set the URL, the events to subscribe to, an optional secret and headers. Apiable signs every payload with the Standard Webhooks scheme.

A webhook tells your systems when something changes in Apiable. You register an endpoint with a URL and the events it should receive, and Apiable sends a signed HTTP POST to that URL each time one of those events fires. You manage webhooks through the Platform API.

How do you configure a webhook?

Create a webhook through the Platform API by sending a POST with the URL to call and the events to subscribe to. The secret and headers are optional. Apiable generates a signing secret if you do not supply one.

POST /api/webhooks

A webhook configuration has these fields:

FieldRequiredWhat it is
urlYesThe endpoint Apiable sends the POST to. It can be any URL that accepts an HTTP POST.
eventsYesThe list of event types this webhook receives. Apiable only posts when one of these fires.
whsecNoThe signing secret, base64-encoded and prefixed whsec_. Apiable generates one between 24 and 64 bytes if you omit it.
headersNoExtra HTTP headers to send with every request, for example an API key your endpoint checks.
authorizationNoA single Authorization header value. Deprecated; use headers instead.

What events can a webhook subscribe to?

Nine event types, covering subscriptions, invoices, and scope grants. You list the ones a webhook should receive in its events field, and Apiable posts only for those.

Event typeFires when
SUBSCRIPTION_CREATEDA developer creates a subscription to a plan.
SUBSCRIPTION_CANCELLEDA subscription is cancelled.
SUBSCRIPTION_CHANGEDA subscription changes.
SUBSCRIPTION_AUTH_CHANGEDA subscription's authentication or credentials change.
INVOICE_ATTENTION_REQUIREDAn invoice needs attention.
SCOPE_GRANT_REQUESTEDA consumer requests a scope grant.
SCOPE_GRANT_APPROVEDA scope grant request is approved.
SCOPE_GRANT_DECLINEDA scope grant request is declined.
SCOPE_GRANT_REVOKEDA scope grant is revoked.

What does a webhook payload look like?

Each delivery is a JSON body that follows the Standard Webhooks spec. It carries the event type, a timestamp, the event data, an id, and an optional source URL. For a subscription event, data includes the subscription id, status, plan, and auth.

{
  "id": "67040bcb1eb964694d999a68",
  "type": "SUBSCRIPTION_CREATED",
  "timestamp": "2026-06-07T10:15:30.123Z",
  "data": {
    "id": "664f1c2a9b1e4a0012ab34cd",
    "status": "ACTIVE"
  },
  "source": "https://your-tenant.apiable.io/api/subscriptions/664f1c2a9b1e4a0012ab34cd"
}

The type matches the event you subscribed to. The data object depends on the subject: subscription events add the id, status, plan, and any auth, while other events carry at least the subject id.

How does Apiable sign webhook payloads?

Apiable signs every payload with the Standard Webhooks scheme. It sends three headers and an HMAC-SHA256 signature computed with your secret, so your endpoint can confirm the request came from Apiable and was not changed.

Every delivery includes these headers:

HeaderWhat it carries
webhook-idA unique id for the message.
webhook-timestampThe send time as an integer unix timestamp, in seconds.
webhook-signatureThe signature, as a space-separated list of versioned signatures, each v1,<base64>.

To verify a delivery, rebuild and compare the signature:

  1. Read webhook-id, webhook-timestamp, and webhook-signature from the request headers.
  2. Build the signed content as {webhook-id}.{webhook-timestamp}.{raw-body}, joined with full stops.
  3. Compute an HMAC-SHA256 over that content using your secret. The secret is base64-encoded after the whsec_ prefix; decode it to get the key bytes.
  4. Base64-encode the HMAC result and compare it to the v1 value in webhook-signature.
  5. Reject the request if the webhook-timestamp is more than 5 minutes from now, to guard against replays.

How does Apiable retry a failed delivery?

Apiable treats 200, 201, 202, and 204 as success. Any other response, or an unreachable endpoint, is a failure. A failed delivery is retried on an hourly schedule, up to 3 attempts, then it stops.

Each attempt is recorded against the webhook as a delivery instance with one of four statuses:

StatusMeaning
PENDINGThe delivery has not succeeded yet and is queued for a retry.
SUCCESSYour endpoint returned a 2xx. The delivery is complete and is not retried.
ERRORThe delivery failed. It is retried hourly until it succeeds or reaches 3 attempts.
SKIPPEDThe event was not sent to this webhook.

How do you see a webhook's delivery history?

Read a webhook's recent delivery records through the Platform API. The history endpoint returns the responses Apiable recorded for that webhook over the last 24 hours, including the status and body of each attempt.

GET /api/webhooks/{id}/history

You can also send a test delivery to confirm your endpoint is reachable before you rely on real events. Apiable posts a signed payload with the type TEST_EVENT to the configured URL and returns the status and body it got back.

GET /api/webhooks/{id}/test

Troubleshooting

Match what you see to the fix.

What you seeWhat to do
The create request is rejected with an invalid whsec errorYour secret must be base64-encoded, prefixed whsec_, and decode to 24 to 64 bytes. Omit whsec to let Apiable generate a valid one.
Deliveries show status ERROR and keep retryingYour endpoint did not return 200, 201, 202, or 204. Check the delivery history for the response Apiable received, and return a 2xx once you accept the event.
A delivery stopped retrying and never arrivedApiable retries up to 3 times, then stops. Fix the endpoint, then update the webhook so future events deliver.
Your endpoint receives the POST but signature verification failsSign {webhook-id}.{webhook-timestamp}.{raw-body} with HMAC-SHA256 over the decoded secret, base64-encode it, and compare to the v1 value. Verify against the raw body, not a re-serialized one.
Verification fails with a timestamp errorThe webhook-timestamp is outside the 5-minute tolerance. Check that your server clock is correct, then accept deliveries within the window.
The test delivery never reaches your endpointThe /test call reports the status and body Apiable received. A connection error there means the URL is wrong or unreachable from Apiable.

Where to next