POST /v1/routines/{routine}/hooks/{hook_id}/test
Signs `body` (default `{"test": true, "sent_at": "<now>"}`) with the hook's current secret and delivers it through the hook ingress the way a sender would, with a fresh `Idempotency-Key`. It is verified, matched against `if` and starts a run like any delivery, and its log entry (`source: test`) is the answer and is listed with the hook's deliveries. Only hooks verified with the `b3os` scheme: B3OS does not hold another provider's signing secret in the clear, so send a test from that provider's settings instead.

Authentication

Bearer Token (b3os_sk_ API key or b3os_pat_ token)

Path Parameters

routine string required path
A routine ID (`rtn_…`) or name. Names are unique per project; `runs`, `hooks`, `validate` and `import` are reserved and cannot be routine names.
Example: "nightly-digest"
hook_id string required path
The hook ID (`hk_…`).
Example: "hk_01m5t3r2qwz23751t0x74bhahz"

Request Body

application/json
body object
The JSON body to deliver; `trigger.body` of the run it starts.

Responses

200 The test delivery's log entry.
application/json
object string REQUIRED
Enum: hook_delivery_entry
hook_id string REQUIRED
received_at string (date-time) REQUIRED
method string REQUIRED
Enum: POST, GET
source string REQUIRED
`edge_replay`: replayed from the edge's queue after the node was down; `test`: `POST …/test`.
Enum: provider, edge_replay, test
status integer REQUIRED
The HTTP status the hook answered.
outcome string REQUIRED
`not_started`: accepted without a run (`if` was false, or the routine is paused); `rejected`: a 4xx; `unavailable`: a 5xx (the edge retries).
Enum: started, deduplicated, not_started, handshake, rejected, unavailable
code string | null REQUIRED
The error code of a 4xx or 5xx.
reason string | null REQUIRED
The `reason` of a `webhook_signature_invalid` (`signature` or `timestamp`).
detail string | null REQUIRED
The error's detail (at most 500 characters).
run_id string | null REQUIRED
delivery_id string | null REQUIRED
deduplicated boolean REQUIRED
handshake string | null REQUIRED
Enum: slack_url_verification, slack_ssl_check, github_ping, get_challenge, null
size integer REQUIRED
Body bytes (the body itself is not kept).
headers object REQUIRED
The allowlisted request headers it had (values up to 256 characters).
400 The request failed validation (`invalid_request`, `invalid_url`).
401 Missing, malformed, expired or revoked credentials (`unauthorized`).
402 The organization has no credits left, or the key reached its spend cap.
403 Authenticated but not allowed (`forbidden`, `egress_denied`).
404 No such hook (`hook_not_found`).
413 The request body exceeds this operation's limit.
415 The Content-Type is not accepted by this operation.
429 A rate, concurrency or quota limit applies (`rate_limited`, `concurrency_limited`, `quota_exceeded`).
500 Something failed inside B3OS (`internal`). Retry with backoff.
503 The node or the product is not available right now (`node_unavailable`, `product_unavailable`, `capacity_unavailable`).
curl -X POST 'https://beta-api.b3os.org/v1/routines/nightly-digest/hooks/hk_01m5t3r2qwz23751t0x74bhahz/test' \  -H 'Authorization: Bearer YOUR_API_TOKEN' \  -H 'Content-Type: application/json' \  -d '{  "body": {    "action": "opened",    "number": 42  }}'
const response = await fetch('https://beta-api.b3os.org/v1/routines/nightly-digest/hooks/hk_01m5t3r2qwz23751t0x74bhahz/test', {  method: 'POST',  headers: {      "Authorization": "Bearer YOUR_API_TOKEN",      "Content-Type": "application/json"  },  body: JSON.stringify({    "body": {      "action": "opened",      "number": 42    }  })});const data = await response.json();console.log(data);
import requestsheaders = {    'Authorization': 'Bearer YOUR_API_TOKEN'}response = requests.post('https://beta-api.b3os.org/v1/routines/nightly-digest/hooks/hk_01m5t3r2qwz23751t0x74bhahz/test', headers=headers, json={  "body": {    "action": "opened",    "number": 42  }})print(response.json())
200 Response
{  "object": "hook_delivery_entry",  "hook_id": "hk_01m5t3r2qwz23751t0x74bhahz",  "received_at": "2026-10-30T18:21:07.448Z",  "method": "POST",  "source": "test",  "status": 202,  "outcome": "started",  "code": null,  "reason": null,  "detail": null,  "run_id": "run_01m5t40dnvfxq40j1zrjj42gpg",  "delivery_id": "evt_01m5t4p5ycda35cq27epnbfqhe",  "deduplicated": false,  "handshake": null,  "size": 30,  "headers": {    "content-type": "application/json",    "user-agent": "b3os-hook-test/1",    "idempotency-key": "evt_01m5t4p5ycda35cq27epnbfqhe"  }}
Ask a question... ⌘I