Account API2026-11Preview
Webhook endpoints
The URLs we POST events to. The events, their payloads, signing and retries are on Webhooks.
Endpoints
- POST/v1/webhook_endpointsCreate an endpoint
- GET/v1/webhook_endpointsList endpoints
- GET/v1/webhook_endpoints/{id}Retrieve an endpoint
- PATCH/v1/webhook_endpoints/{id}Update an endpoint
- DELETE/v1/webhook_endpoints/{id}Delete an endpoint
- POST/v1/webhook_endpoints/{id}/rotate_secretRotate the secret
- POST/v1/webhook_endpoints/{id}/testSend a test event
- GET/v1/webhook_endpoints/{id}/deliveriesList deliveries
- POST/v1/webhook_endpoints/{id}/deliveries/{delivery}/retrySend a delivery again
The Webhook endpoint object
idstring- Starts we_.
urlstring- An https URL of yours that answers 2xx.
descriptionstring|null- For you.
events[]array- The event types to send, or
*for all, including types added later: order.created, order.paid, order.bought, order.checked, order.shipped, product.cost_changed, product.out_of_stock, qc.issue. statusstring- enabled, or disabled (by you, or by us after five days in which every delivery failed; we email you first).
api_versionstring- The version event payloads are written in; the key's at creation.
secretstring- The signing secret. Only in the answers to create and rotate.
{
"id": "we_3d8s",
"url": "https://acme-goods.com/hooks/ninjabuy",
"description": "Order sync",
"events": ["order.shipped", "product.out_of_stock", "qc.issue"],
"status": "enabled",
"api_version": "2026-11",
"created_at": "2026-11-01T08:00:00Z"
}Create an endpoint
POST/v1/webhook_endpoints
Answers the signing secret once: store it now. Up to 16 endpoints per account.
Scopewebhooks:write
Body
urlstringrequired- https only.
events[]arrayrequired- Event types, or ["*"].
descriptionstring- Optional.
Errors
| Status | Type | When |
|---|---|---|
| 400 | bad-body | The URL is not https, or an event type is unknown. |
| 409 | invalid-state | The account has 16 endpoints already. |
curl -X POST "https://www.ninjabuy.com/api/v1/webhook_endpoints" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://acme-goods.com/hooks/ninjabuy",
"events": ["order.shipped", "product.out_of_stock", "qc.issue"],
"description": "Order sync"
}'HTTP/2 201 Created
{
"id": "we_3d8s",
"url": "https://acme-goods.com/hooks/ninjabuy",
"description": "Order sync",
"events": ["order.shipped", "product.out_of_stock", "qc.issue"],
"status": "enabled",
"api_version": "2026-11",
"created_at": "2026-11-01T08:00:00Z",
"secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}List endpoints
GET/v1/webhook_endpoints
Every endpoint on the account, without secrets.
Scopewebhooks:write
curl "https://www.ninjabuy.com/api/v1/webhook_endpoints" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{
"data": [
{
"id": "we_3d8s",
"url": "https://acme-goods.com/hooks/ninjabuy",
"description": "Order sync",
"events": ["order.shipped", "product.out_of_stock", "qc.issue"],
"status": "enabled",
"api_version": "2026-11",
"created_at": "2026-11-01T08:00:00Z"
}
],
"has_more": false,
"cursor": null
}Retrieve an endpoint
GET/v1/webhook_endpoints/{id}
One endpoint, without its secret.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{
"id": "we_3d8s",
"url": "https://acme-goods.com/hooks/ninjabuy",
"description": "Order sync",
"events": ["order.shipped", "product.out_of_stock", "qc.issue"],
"status": "enabled",
"api_version": "2026-11",
"created_at": "2026-11-01T08:00:00Z"
}Update an endpoint
PATCH/v1/webhook_endpoints/{id}
Change its URL or events, or disable and enable it. Enabling sends what it missed in the last 3 days.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
Body
urlstring- https only.
events[]array- Event types, or ["*"].
descriptionstring- Optional.
statusstring- Optional. enabled or disabled.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl -X PATCH "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Content-Type: application/json" \
-d '{ "events": ["*"] }'HTTP/2 200 OK
{
"id": "we_3d8s",
"url": "https://acme-goods.com/hooks/ninjabuy",
"description": "Order sync",
"events": ["*"],
"status": "enabled",
"api_version": "2026-11",
"created_at": "2026-11-01T08:00:00Z"
}Delete an endpoint
DELETE/v1/webhook_endpoints/{id}
Stops every delivery to it at once, retries included.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl -X DELETE "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{ "id": "we_3d8s", "deleted": true }Rotate the secret
POST/v1/webhook_endpoints/{id}/rotate_secret
Answers a new secret. For 24 hours we sign with both, so the webhook-signature header carries two signatures and either verifies: deploy the new one, then let the old one lapse.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl -X POST "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s/rotate_secret" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Idempotency-Key: $(uuidgen)"HTTP/2 200 OK
{
"id": "we_3d8s",
"secret": "whsec_C2FVsBQIhrscChlQIMV+b5sSYspob7oD",
"previous_expires_at": "2026-11-05T09:30:00Z"
}Send a test event
POST/v1/webhook_endpoints/{id}/test
Sends a sample of one event type, signed like any other, with test: true. Answers how your endpoint replied.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
Body
typestringrequired- An event type.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl -X POST "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s/test" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "type": "qc.issue" }'HTTP/2 200 OK
{
"delivery": "dlv_0k2p",
"event": "evt_test_6c3h",
"response_status": 200,
"duration_ms": 182
}List deliveries
GET/v1/webhook_endpoints/{id}/deliveries
Every attempt of the last 30 days, newest first: what we sent, how you answered and when we retry.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
Query parameters
statusstring- Optional. succeeded, retrying or failed.
eventstring- Optional. An event id.
limit, cursor- Pagination
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s/deliveries?status=retrying" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11"HTTP/2 200 OK
{
"data": [
{
"id": "dlv_0k3a",
"event": "evt_4m2x",
"type": "order.shipped",
"status": "retrying",
"attempts": 3,
"last_response_status": 502,
"next_attempt_at": "2026-11-03T08:35:00Z"
}
],
"has_more": false,
"cursor": null
}Send a delivery again
POST/v1/webhook_endpoints/{id}/deliveries/{delivery}/retry
Sends the event now, with the same webhook-id, whatever its state. Retries already scheduled go on.
Scopewebhooks:write
Path parameters
idstringrequired- The endpoint's id.
deliverystringrequired- A delivery id.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not-found | No such endpoint on this account. |
curl -X POST "https://www.ninjabuy.com/api/v1/webhook_endpoints/we_3d8s/deliveries/dlv_0k3a/retry" \
-H "Authorization: Bearer $NINJABUY_API_KEY" \
-H "NinjaBuy-Version: 2026-11" \
-H "Idempotency-Key: $(uuidgen)"HTTP/2 202 Accepted
{
"delivery": "dlv_0k3a",
"status": "retrying",
"next_attempt_at": "2026-11-03T08:01:10Z"
}