Documentation menu

API reference

Webhook endpoints

Create, list, pause, test and delete the URLs that receive job events, rotate their secrets, and read the signing secret for per-job webhooks.

Overview

A webhook endpoint is a URL on your server. When a job finishes, the API sends an event to every enabled endpoint of the account. An account can have up to 10 endpoints. Endpoints can also be managed in the dashboard.

MethodPathPurpose
POST/v1/webhook_endpointsCreate an endpoint
GET/v1/webhook_endpointsList endpoints
PATCH/v1/webhook_endpoints/{id}Pause or resume an endpoint
POST/v1/webhook_endpoints/{id}/rotate_secretReplace its secret
POST/v1/webhook_endpoints/{id}/testSend it a test event
DELETE/v1/webhook_endpoints/{id}Delete an endpoint
GET/v1/webhook_endpoints/signing_secretGet the account signing secret
  • Endpoints belong to the account, not to a key or a mode. An endpoint receives the events of live jobs and of test jobs. Each event says which with livemode.
  • Each endpoint has its own secret, which signs the deliveries to that endpoint. It is shown once, when the endpoint is created, and once more each time it is rotated.
  • A job can also name a webhook_url of its own. Deliveries to that URL are signed with a different secret: the account's signing secret, described below.

See Webhooks for how to receive and verify an event.

The webhook endpoint object

json
{
  "id": "whk_R4tYp9LmXc2VbN7qWz0K",
  "object": "webhook_endpoint",
  "url": "https://example.com/hooks/smol",
  "enabled": true,
  "created_at": "2026-10-01T09:30:12.480Z"
}
FieldTypeDescription
idstringThe endpoint id: whk_ followed by 20 letters and digits.
objectstringAlways "webhook_endpoint".
urlstringThe URL that receives events.
enabledbooleanWhether events are sent to this endpoint. true for an endpoint you create. false while it is paused.
created_atstringWhen the endpoint was created.

Create an endpoint

POST/v1/webhook_endpoints

Send a JSON body. A field that is not listed here is refused with bad_request.

FieldTypeDescription
url *stringA public https URL. It follows the same URL rules as a job's URLs.
bash
curl -X POST "https://api.smolmac.com/v1/webhook_endpoints" \
  -H "Authorization: Bearer $SMOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/hooks/smol"}'

The response has status 201. It is the endpoint object with one more field, secret.

201 Created
{
  "id": "whk_R4tYp9LmXc2VbN7qWz0K",
  "object": "webhook_endpoint",
  "url": "https://example.com/hooks/smol",
  "enabled": true,
  "created_at": "2026-10-01T09:30:12.480Z",
  "secret": "whsec_h2Kd8LqT5xZc1VbN9mWp3RyA7sJf0GuE"
}

The secret is whsec_ followed by 32 letters and digits. The same URL can be registered more than once. Each registration is a separate endpoint with its own secret and receives its own delivery.

List endpoints

GET/v1/webhook_endpoints

Returns every endpoint of the account, newest first. The list is not paginated, so has_more is always false. Secrets are not included.

bash
curl "https://api.smolmac.com/v1/webhook_endpoints" \
  -H "Authorization: Bearer $SMOL_API_KEY"
200 OK
{
  "object": "list",
  "data": [
    {
      "id": "whk_R4tYp9LmXc2VbN7qWz0K",
      "object": "webhook_endpoint",
      "url": "https://example.com/hooks/smol",
      "enabled": true,
      "created_at": "2026-10-01T09:30:12.480Z"
    }
  ],
  "has_more": false
}

Pause or resume an endpoint

PATCH/v1/webhook_endpoints/{id}

Send a JSON body with one field. A field that is not listed here is refused with bad_request.

FieldTypeDescription
enabled *booleanfalse pauses deliveries to the endpoint. true resumes them.
bash
curl -X PATCH "https://api.smolmac.com/v1/webhook_endpoints/whk_R4tYp9LmXc2VbN7qWz0K" \
  -H "Authorization: Bearer $SMOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled":false}'
200 OK
{
  "id": "whk_R4tYp9LmXc2VbN7qWz0K",
  "object": "webhook_endpoint",
  "url": "https://example.com/hooks/smol",
  "enabled": false,
  "created_at": "2026-10-01T09:30:12.480Z"
}
  • A paused endpoint keeps its id, its URL and its secret.
  • Jobs that finish while the endpoint is paused send it nothing, and those events are not sent later, when it is resumed.
  • Deliveries that were already queued for a job that finished before the pause, including their retries, are still attempted.
  • The URL of an endpoint cannot be changed. To use another URL, create a new endpoint and delete the old one.

Rotate the secret

POST/v1/webhook_endpoints/{id}/rotate_secret

Gives the endpoint a new secret. The request has no body. The response is the endpoint object with the new secret, which is shown only here.

bash
curl -X POST "https://api.smolmac.com/v1/webhook_endpoints/whk_R4tYp9LmXc2VbN7qWz0K/rotate_secret" \
  -H "Authorization: Bearer $SMOL_API_KEY"
200 OK
{
  "id": "whk_R4tYp9LmXc2VbN7qWz0K",
  "object": "webhook_endpoint",
  "url": "https://example.com/hooks/smol",
  "enabled": true,
  "created_at": "2026-10-01T09:30:12.480Z",
  "secret": "whsec_Lm3Xc7VbN1qWz9RtY5pKd2HsF8gJ0aEu"
}
  • Events for jobs that finish after the call are signed with the new secret. The old secret is not used for them, and there is no period in which both sign.
  • A delivery that was queued before the call keeps the secret it was queued with, on every retry. Retries can run for about 21 hours.
  • So have your receiver accept both secrets while you switch: deploy the new one next to the old, and remove the old one a day later.
  • The account signing secret, which signs deliveries to a job's webhook_url, cannot be rotated with this request.

Send a test event

POST/v1/webhook_endpoints/{id}/test

Sends one event of type ping to the endpoint, signed with its secret, and answers with what the endpoint returned. Use it to check your signature verification without running a job. The request has no body.

bash
curl -X POST "https://api.smolmac.com/v1/webhook_endpoints/whk_R4tYp9LmXc2VbN7qWz0K/test" \
  -H "Authorization: Bearer $SMOL_API_KEY"
200 OK
{
  "object": "webhook_test",
  "event_id": "evt_Tq6Wn1YdK8sLc3VbX0mR",
  "delivered": true,
  "status": 204,
  "duration_ms": 182
}
FieldTypeDescription
objectstringAlways "webhook_test".
event_idstringThe id of the ping event that was sent.
deliveredbooleantrue when the endpoint answered with a status from 200 to 299.
statusintegerThe HTTP status the endpoint returned. 0 if it did not answer within 10 seconds or could not be reached.
duration_msintegerHow long the delivery took, in milliseconds.
  • The request itself answers 200 whether or not the delivery worked. Read delivered.
  • The event is sent once and is not retried. Redirects are not followed.
  • The event's livemode is true when you call with a live key and false with a test key.
  • A paused endpoint can be tested. The test does not resume it.

Delete an endpoint

DELETE/v1/webhook_endpoints/{id}

Deletes the endpoint. Jobs that finish from now on send it nothing. Deliveries that were already queued for a job that finished earlier, including their retries, are still attempted.

bash
curl -X DELETE "https://api.smolmac.com/v1/webhook_endpoints/whk_R4tYp9LmXc2VbN7qWz0K" \
  -H "Authorization: Bearer $SMOL_API_KEY"
200 OK
{
  "id": "whk_R4tYp9LmXc2VbN7qWz0K",
  "object": "webhook_endpoint",
  "deleted": true
}

Returns 404 not_found if the account has no endpoint with that id.

Get the signing secret

GET/v1/webhook_endpoints/signing_secret

Returns the account's signing secret. It signs deliveries to a URL given in a job's webhook_url, when that URL is not one of your registered endpoints. There is one such secret per account. It is created the first time it is needed, and this request returns the same value every time after that.

bash
curl "https://api.smolmac.com/v1/webhook_endpoints/signing_secret" \
  -H "Authorization: Bearer $SMOL_API_KEY"
200 OK
{
  "object": "webhook_signing_secret",
  "secret": "whsec_Qe7Zr2MnB5vXc8LkJ1hGf4DsA9pWy0Tu"
}
A delivery toIs signed with
A registered endpointThe secret of that endpoint, returned when it was created or last rotated.
A job's webhook_url that is not a registered endpointThe account signing secret, returned by this request.
A job's webhook_url that is the same as the URL of an enabled registered endpointThe secret of that endpoint. The event is delivered once, not twice.

Errors

CodeStatusEndpointWhen
bad_request400CreateThe body is not a JSON object, has an unknown field, url is missing or is not a public https URL, or the account already has 10 endpoints.
bad_request400Pause or resume, testPause or resume: the body has an unknown field, or enabled is not true or false. Test: the URL of the endpoint no longer meets the URL rules.
not_found404Pause or resume, rotate, test, deleteNo endpoint with that id on this account.
missing_key, invalid_key, revoked_key401AllThe API key is missing, wrong or revoked.
no_payment_method, payment_required402AllA live key on an account with no plan, or with an unpaid invoice.
account_suspended, ip_not_allowed403AllThe account is suspended, or the key may not be used from this IP address.