Send a test delivery
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.
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/jsonbody
object
The JSON body to deliver; `trigger.body` of the run it starts.
Responses
200
The test delivery's log entry.
application/jsonobject
string
REQUIRED
Enum:
hook_delivery_entryhook_id
string
REQUIRED
received_at
string (date-time)
REQUIRED
method
string
REQUIRED
Enum:
POST, GETsource
string
REQUIRED
`edge_replay`: replayed from the edge's queue after the node was down; `test`: `POST …/test`.
Enum:
provider, edge_replay, teststatus
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, unavailablecode
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, nullsize
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" }}
API Playground
Try this endpoint
POST
/v1/routines/{routine}/hooks/{hook_id}/test