Account API2026-11Preview

Webhook endpoints

The URLs we POST events to. The events, their payloads, signing and retries are on Webhooks.

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.
webhook_endpoint
{
  "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

StatusTypeWhen
400bad-bodyThe URL is not https, or an event type is unknown.
409invalid-stateThe 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"
  }'
Response 201
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"
Response 200
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

StatusTypeWhen
404not-foundNo 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"
Response 200
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

StatusTypeWhen
404not-foundNo 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": ["*"] }'
Response 200
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

StatusTypeWhen
404not-foundNo 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"
Response 200
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

StatusTypeWhen
404not-foundNo 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)"
Response 200
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

StatusTypeWhen
404not-foundNo 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" }'
Response 200
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

StatusTypeWhen
404not-foundNo 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"
Response 200
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

StatusTypeWhen
404not-foundNo 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)"
Response 202
HTTP/2 202 Accepted

{
  "delivery": "dlv_0k3a",
  "status": "retrying",
  "next_attempt_at": "2026-11-03T08:01:10Z"
}