Deliver a pack trigger webhook
The URL B3OS registers with a provider for a webhook trigger subscription (`tsub_…`). The delivery is verified with the trigger's `verify` scheme from its pack manifest, deduplicated by its dedupe key, filtered, and turned into events for the subscription's consumers. Timestamped schemes (`stripe`, `slack`, `standard_webhooks`, and `hmac_sha256`, which always is) refuse a delivery whose timestamp is more than `verify.toleranceS` seconds (at most 300) from the node clock: `401 webhook_signature_invalid` with `reason: timestamp`, so a captured delivery cannot be replayed later; inside the window a repeat is a duplicate (the dedupe key is remembered for 73 hours, up to 10,000 keys per subscription). Providers that send a verification handshake (Slack's `url_verification`) get the answer the manifest's `handshake` defines. A paused subscription, a filtered delivery and an authentic delivery whose event does not match the trigger's `eventSchema` are acknowledged with `202` and emit nothing. No API key is used: the unguessable hook ID plus the provider signature authenticate it. The verified signature is remembered with the dedupe key, so a captured delivery replayed with a new value in an unsigned header (GitHub's `X-GitHub-Delivery`) is still a duplicate; `github` signs no timestamp, so such a replay is refused only while the signature is remembered (73 hours, up to 10,000 per subscription). While the node is unreachable the edge queues deliveries (`202` with `x-b3os-queued: true`) and replays them in order, attesting when it received each one: `x-b3os-hook-received-at` (Unix seconds), `x-b3os-edge-kid` and `x-b3os-edge-sig`, an Ed25519 signature by the edge key over `b3os-hook-v1 <node> <path> <received_at> <hex sha256(body)>`, plus `x-b3os-hook-replay` (the attempt, 0 first). The node verifies the attestation when it is present (`401 webhook_signature_invalid`, `reason: signature` or `timestamp`, when it does not verify or the receive time is more than 300 seconds ahead or 72 hours plus 300 seconds behind the node clock) and, on a replay (`x-b3os-hook-replay` ≥ 1), applies the provider's timestamp tolerance to the edge's receive time instead of its own clock, so a delivery queued during an outage is not refused as stale. The provider signature is required either way. A replay signed by an edge key id this node does not trust yet, whose provider timestamp is outside the tolerance of the node clock, answers `503 hook_attestation_unverifiable` with `Retry-After: 60` (the same rule as the routines hook route). The node answers 5xx only when a later attempt can succeed (also: the vault, the routine engine or the pinned pack version is not available right now, `503 product_unavailable` or `503 pack_unavailable`); the edge keeps those deliveries and retries them. A subscription whose signing secret cannot be used answers `422 connection_required` or `422 connection_mismatch`.
/v1/actions/hooks/{hook_id}
Path Parameters
hook_id
string
required
path
"hk_01m5t6qg7cfcq459vcqvpj74jj"Request Body
application/jsonResponses
application/jsoncurl -X POST 'https://beta-api.b3os.org/v1/actions/hooks/hk_01m5t6qg7cfcq459vcqvpj74jj' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "id": "evt_1Q2w3E4r5T6y7U8i", "type": "invoice.paid"}'
const response = await fetch('https://beta-api.b3os.org/v1/actions/hooks/hk_01m5t6qg7cfcq459vcqvpj74jj', { method: 'POST', headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "id": "evt_1Q2w3E4r5T6y7U8i", "type": "invoice.paid" })});const data = await response.json();console.log(data);
import requestsheaders = { 'Authorization': 'Bearer YOUR_API_TOKEN'}response = requests.post('https://beta-api.b3os.org/v1/actions/hooks/hk_01m5t6qg7cfcq459vcqvpj74jj', headers=headers, json={ "id": "evt_1Q2w3E4r5T6y7U8i", "type": "invoice.paid"})print(response.json())
{ "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}
Try this endpoint
/v1/actions/hooks/{hook_id}