Webhooks
Send another app's webhooks to a webhook URL that Albastar Corp. sets up, and read each delivery's outcome.
Access: Webhook URLs set up and issued by Albastar Corp.
A webhook URL turns HTTP requests from another app (a CI, a monitor, a shop) into events of one source, without a publish key. Albastar Corp. sets up the webhook on a source, with the rules that turn each request into events, and hands over the URL.
Send a delivery
The webhook URL is https://api.albastov.com/v1/events/hooks/in/{token}, with a 43-character token. Paste the URL
into the sending app's webhook settings. A delivery from curl takes the same path as a delivery from the sending app.
curl https://api.albastov.com/v1/events/hooks/in/$ALBASTAR_WEBHOOK_TOKEN \
-H "Content-Type: application/json" \
-d '{
"project": "web",
"deployment": {"id": "dpl_4812", "state": "ERROR", "commit": "9f3c2e1"}
}'{
"ok": true,
"outcome": "evt_01M6GEVFQHS6V8X2Z4B7D9G1J5",
"events": ["evt_01M6GEVFQHS6V8X2Z4B7D9G1J5"]
}The body is JSON, a form (application/x-www-form-urlencoded) or any text, at most 2 MB. An empty body reads the
URL's query string as a form. An accepted delivery is answered 200 with ok, the delivery's outcome and the ids of
the events the delivery stored.
New webhooks
A new webhook starts pending: the API keeps each delivery, answers held: pending review with "events": [], and
publishes nothing until Albastar Corp. activates the webhook. Send one test delivery from the app after pasting the
URL; the kept delivery shows Albastar Corp. what the app sends.
{
"ok": true,
"outcome": "held: pending review",
"events": []
}Outcomes
outcome | Meaning |
|---|---|
evt_… | One event, stored; for a repeated idempotency key, the event stored the first time |
held | One event, held: at most 5 events of one webhook source a minute reach readers one by one, and the rest arrive after the minute as one summary event |
held: pending review | No event: the webhook is pending; the delivery is kept |
dropped: <reason> | No event: one of the webhook's rules dropped the item (rule 1, case 3, or the rule's own reason) |
dropped: duplicate of delivery <id> | No event: the same body arrived within the last 10 minutes |
dropped: split: 0 items | No event: the request held an empty list of items |
dropped: invalid: <message> | No event: the event the request made fails field validation |
dropped: rate limited | No event: the source is over its rate |
error: <message> | No event: storing the event failed |
2 events: evt_a,held,dropped: rule 1 | A request that holds several items: one entry per item, in order; the count includes stored and held items only |
…; url dropped: host <host> not allowed | The event's url pointed outside the hosts allowed for the webhook and was removed |
…; 12 items over 1000 dropped | The request held more than 1,000 items; items past 1,000 make no event |
…; mapping error: <message> | The webhook's rules failed on this request; the delivery made one plain event of type webhook instead |
Duplicates
A sender may deliver one request twice: a retry after a timeout, or a manual resend. The API dedupes on the first key available:
| Key | Dedupe |
|---|---|
| An idempotency key the webhook's rules read from the request | An event with a key stored in the last 7 days returns the stored event |
The first of the headers X-GitHub-Delivery, Idempotency-Key, Webhook-Id, X-Webhook-Id, X-Delivery-Id | As the idempotency key |
| SHA-256 of the body as received | dropped: duplicate of delivery <id> when the source had a delivery with the same body in the last 10 minutes |
The 10 minutes count from the original delivery, not from its duplicates: a body resent every 5 minutes makes one event every 10 minutes. Set one of the delivery headers above, the same on every retry, to dedupe retries of one delivery.
Signatures
Albastar Corp. may set a signature on the webhook: the sending app signs each request body with a secret shared with
Albastar Corp., and the API recomputes the signature. A required signature refuses every delivery without a valid
one with 401 bad_signature; an optional signature checks only deliveries that carry the header.
| Scheme | The sending app sends |
|---|---|
hmac-sha256, hmac-sha1 | The HMAC of the raw body under the secret, in the agreed encoding (hex in any case, or base64), in the agreed header (default X-Signature), after the agreed prefix (for example sha256=) |
stripe | Stripe-Signature: t=…,v1=…: HMAC-SHA256 of t.body; any v1 may match; t within 5 minutes of the API's clock |
GitHub's webhook secret, for example, uses scheme hmac-sha256, header X-Hub-Signature-256 and prefix sha256=.
Limits and errors
| Limit | Value |
|---|---|
| Body | 2 MB |
| Deliveries per source | 120 a minute, bursts of 30; then 429 rate_limited with Retry-After |
| Refused requests per client address | 30, refilling 1 every 2 seconds, across all webhook URLs; past the allowance, every webhook URL answers the address 429 rate_limited |
Only refused requests (401, 404) count toward the client address allowance; accepted deliveries never count.
| Status | Code | Meaning |
|---|---|---|
400 | bad_delivery | The webhook refused the body as malformed |
401 | bad_signature | Missing or invalid signature where one is required or sent |
404 | hook_not_found | Unknown token, a webhook turned off, or an archived source |
413 | body_too_large | Body over 2 MB |
429 | rate_limited | Over a limit above; wait Retry-After seconds |
503 | seal_key_missing | Webhook signatures cannot be checked right now; retry later |
Token
The token is the webhook's credential: keep the URL out of public repositories and logs. After a leak, ask Albastar
Corp. to rotate the token; the old URL then returns 404 hook_not_found at once.
Reference
- Receive a webhook delivery: the
route, response, every
outcomevalue and error code.