Skip to main content
All endpoints accept and return JSON, require a PAT in Authorization: Bearer <token>, and accept Content-Type: application/json. Base URL: https://api.keebai.com/v1.

Create a subscription

POST /v1/webhooks — returns the raw secret only once.
Body Response 201
secret is returned only in this response. You will never see it again. Store it in your secret manager. If you lose it, you have to rotate (POST /v1/webhooks/:id/rotate-secret), which invalidates the old one.

List subscriptions

GET /v1/webhooks — returns every subscription on your company.
Response 200
secret is not included in list or get-by-id. Only secret_prefix (the first 12 chars), which is enough to visually identify which key you’re using.

Get a subscription

GET /v1/webhooks/:id
Same shape as a list item.

Update a subscription

PATCH /v1/webhooks/:id — every field is optional.
Useful for:
  • Reactivating a subscription that was auto-disabled by excessive failures (is_active: true).
  • Adding or removing events without recreating it (preserves the secret).
  • Changing the URL (preserves the secret).

Rotate secret

POST /v1/webhooks/:id/rotate-secret
Response 200 — same shape as create, with a new secret. The old one is invalidated immediately. For zero-downtime rotation, see security.

Dispatch a synthetic event (test)

POST /v1/webhooks/:id/test — sends a synthetic envelope with data._test: true to your URL.
Response 202
Useful in CI: chain a webhooks test after deploying your endpoint to verify that HMAC verification still works.

List deliveries

GET /v1/webhooks/:id/deliveries?limit=50&cursor=<delivery_id>
Response 200
status:
  • pending — queued, not yet attempted.
  • success — 2xx response.
  • failed — non-retryable failure (4xx other than 408/429), or retries are exhausted but still in the retry window.
  • dead — exceeded the 5 attempts, no further retries.

Delete a subscription

DELETE /v1/webhooks/:id
Response 204 — no body. Future events are not sent to this URL.

Common errors

Auto-disable

If a subscription accumulates 50 consecutive dead deliveries, we mark it is_active: false with disabled_reason: 'excessive_failures' and email the owner. Reactivate via PATCH /v1/webhooks/:id { "is_active": true } once you’ve fixed the endpoint. This stops an endpoint under maintenance from collecting noise for hours. The counter resets on the next successful delivery.