Utopia PaymentsDocs
Webhooks

Create a webhook endpoint

The response includes the endpoint's signing `secret`. Registers a URL that receives signed events. The URL must be `https://` on a public host and carry no credentials; private, loopback, link-local and internal addresses are refused with `INVALID_REQUEST_BODY`, including hosts whose DNS answers with one. An endpoint created without `event_types` receives every event type. Each mode allows 16 endpoints (`409 LIMIT_REACHED`). Store the `secret` when you read it here: no other response repeats it except `GET /webhooks/{id}/secret`. Send `Idempotency-Key` so a retried request does not add a second endpoint — a replayed response has the secret stripped out, since a stored response must not keep it.

POST
/webhooks

The response includes the endpoint's signing secret.

Registers a URL that receives signed events. The URL must be https:// on a public host and carry no credentials; private, loopback, link-local and internal addresses are refused with INVALID_REQUEST_BODY, including hosts whose DNS answers with one. An endpoint created without event_types receives every event type. Each mode allows 16 endpoints (409 LIMIT_REACHED).

Store the secret when you read it here: no other response repeats it except GET /webhooks/{id}/secret. Send Idempotency-Key so a retried request does not add a second endpoint — a replayed response has the secret stripped out, since a stored response must not keep it.

Authorization

secretKey
AuthorizationBearer <token>

Your secret key: sk_live_… or sk_test_….

In: header

Header Parameters

Idempotency-Key?string

Retrying with the same key returns the first response instead of creating a duplicate. 1 to 255 printable ASCII characters (INVALID_IDEMPOTENCY_KEY otherwise), remembered for 24 hours per key's merchant and mode. A replayed answer carries idempotent-replayed: true. The same key with a different body is refused with 422 IDEMPOTENCY_KEY_REUSED; while the first request is still running, 409 IDEMPOTENCY_KEY_IN_USE. A request that failed with a 5xx is not remembered, so it can simply be retried.

Lengthlength <= 255

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/webhooks" \  -H "Content-Type: application/json" \  -d '{    "url": "https://your-app.example/webhooks/utopia",    "description": "Order fulfilment",    "event_types": [      "payment.succeeded",      "refund.succeeded"    ]  }'
{  "object": "webhook",  "webhook_id": "wh_0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b",  "url": "https://your-app.example/webhooks/utopia",  "description": "Order fulfilment",  "event_types": [    "payment.succeeded",    "refund.succeeded"  ],  "disabled": false,  "livemode": true,  "created_at": "2026-09-10T08:30:00.000Z",  "secret": "whsec_8ZPqvj0oNn4cKcGbHkA6uRGyXwZ1TtQ2"}