> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spherepay.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing Webhook Endpoints

> Register webhook endpoints, subscribe to events, and understand endpoint limits, states, and the delete-and-recreate update model.

A webhook endpoint is a URL you register with SpherePay together with the list of events it should receive. This page covers the full endpoint lifecycle: creating an endpoint, listing and retrieving endpoints, and deleting them.

## Register an endpoint

Create an endpoint with `POST /v2/webhook-endpoints`:

```bash theme={"dark"}
curl -X POST https://api.spherepay.co/v2/webhook-endpoints \
  -H "Authorization: Bearer {{api_key}}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/sphere-webhook",
    "subscribedEvents": ["customer.approved", "customer.rejected", "transfer.*"],
    "apiVersion": "2026-08-01",
    "description": "Production onboarding and transfer events",
    "metadata": { "team": "payments", "environment": "prod" }
  }'
```

| Field              | Required | Description                                                                                                                                                                      |
| ------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`              | Yes      | The URL SpherePay delivers events to. Must be HTTPS in live mode. Maximum 2,048 characters.                                                                                      |
| `subscribedEvents` | Yes      | One or more event names from the [event catalog](/concepts/webhooks/event-catalog), or a wildcard: `*` (all events) or a resource wildcard such as `customer.*` or `transfer.*`. |
| `apiVersion`       | Yes      | A `YYYY-MM-DD` API version date. Must be a valid calendar date and must not be in the future.                                                                                    |
| `description`      | No       | Free-text label, up to 500 characters.                                                                                                                                           |
| `metadata`         | No       | Key-value pairs for your own bookkeeping — for example, to track registered endpoints within your system.                                                                        |

The response returns the endpoint and its signing secret:

```json theme={"dark"}
{
  "id": "whk_01HXP9TN3J2ABC",
  "url": "https://api.example.com/sphere-webhook",
  "subscribedEvents": ["customer.approved", "customer.rejected", "transfer.*"],
  "status": "enabled",
  "apiVersion": "2026-08-01",
  "secret": "whsec_9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c",
  "description": "Production onboarding and transfer events",
  "metadata": { "team": "payments", "environment": "prod" },
  "createdAt": "2026-08-07T10:00:00Z",
  "updatedAt": "2026-08-07T10:00:00Z"
}
```

<Warning>
  The `secret` (prefixed `whsec_`) is returned **exactly once**, in the creation response. It is never returned by `GET` requests and cannot be retrieved later. Store it securely — you need it to [verify the signature](/concepts/webhooks/verifying-signatures) on every delivery. Each endpoint has its own distinct secret; secrets are never shared across endpoints.
</Warning>

Newly created endpoints are `enabled` immediately and begin receiving events that match their subscription.

## Updating an endpoint: delete and recreate

There is currently **no update operation** for webhook endpoints. To change an endpoint's URL, subscribed events, or any other property, delete the endpoint and create a new one. The same applies to rotating a signing secret — deleting an endpoint invalidates its secret, and the replacement endpoint receives a fresh one.

<Info>
  In-place endpoint updates are coming soon — a future release will let you modify an existing endpoint's URL and subscriptions without recreating it. Until then, use the delete-and-recreate flow below.
</Info>

For a zero-gap migration:

1. Create the new endpoint with the updated configuration. Both endpoints now receive events.
2. Confirm the new endpoint is receiving and verifying deliveries.
3. Delete the old endpoint.

<Note>
  During step 1 both endpoints receive matching events, so your handlers should be idempotent — deduplicate on the event `id` in the payload body.
</Note>

## List and retrieve endpoints

```bash theme={"dark"}
curl "https://api.spherepay.co/v2/webhook-endpoints?page=1&limit=10" \
  -H "Authorization: Bearer {{api_key}}"
```

List query parameters:

| Parameter          | Description                                                                                                                                        |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `page`             | Page number, starting at `1` (default `1`).                                                                                                        |
| `limit`            | Results per page (default `10`, maximum `100`).                                                                                                    |
| `status`           | Filter by endpoint state: `enabled`, `disabled`, or `errored`.                                                                                     |
| `subscribedEvents` | Comma-separated event names; returns endpoints subscribed to at least one of them. Wildcard values (`*`, `customer.*`, `transfer.*`) are accepted. |

<Note>
  The `subscribedEvents` filter matches **literally** against each endpoint's subscription list — it does not expand wildcards. Filtering by `transfer.*` returns endpoints that subscribed with the `transfer.*` wildcard itself, not endpoints subscribed to individual events like `transfer.succeeded` (and vice versa). To find every endpoint that would receive a given event, filter by both forms: `subscribedEvents=transfer.succeeded,transfer.*,*`.
</Note>

List responses use SpherePay's standard pagination envelope: `{ "data": [...], "page", "limit", "total", "totalPages", "hasNext", "hasPrevious" }`.

Retrieve a single endpoint with `GET /v2/webhook-endpoints/{id}`. The `secret` field is never included.

## Delete an endpoint

```bash theme={"dark"}
curl -X DELETE https://api.spherepay.co/v2/webhook-endpoints/{{webhook_endpoint_id}} \
  -H "Authorization: Bearer {{api_key}}"
```

Deletion returns `204 No Content`, transitions the endpoint to the `deleted` state, invalidates its signing secret, and stops all future deliveries. **This is terminal and cannot be undone** — to resume delivery, create a new endpoint.

## Endpoint limits

Each application may have at most **6 active webhook endpoints** — endpoints in the `enabled`, `disabled`, or `errored` state. Deleted endpoints do not count toward the limit. Exceeding it returns `409 Conflict`.

## Endpoint states

| State      | Meaning                                                                                  |
| ---------- | ---------------------------------------------------------------------------------------- |
| `enabled`  | Receiving deliveries. The initial state after registration.                              |
| `disabled` | Not receiving deliveries.                                                                |
| `errored`  | Reserved for delivery-failure handling in a future release.                              |
| `deleted`  | Terminal. The endpoint no longer exists for delivery purposes and its secret is invalid. |

Only `enabled` endpoints receive deliveries.

<Note>
  **Failed deliveries do not disable your endpoint.** In the current release, SpherePay never changes an endpoint's state based on delivery outcomes: if your endpoint returns a non-`2xx` response or times out, the individual delivery is marked `failed` and no automatic retry occurs, but the endpoint stays `enabled` and continues receiving subsequent events. Recover missed events with a [manual replay](/concepts/webhooks/events-and-replays#replaying-a-delivery).
</Note>

## Errors

| Condition                                | HTTP status | Description                                                      |
| ---------------------------------------- | ----------- | ---------------------------------------------------------------- |
| Unknown event name in `subscribedEvents` | `400`       | The event type is not in the published catalog.                  |
| Invalid `apiVersion`                     | `400`       | Not a valid `YYYY-MM-DD` calendar date, or a date in the future. |
| Endpoint not found                       | `404`       | The webhook endpoint ID does not exist.                          |
| Endpoint limit exceeded                  | `409`       | The application already has 6 active endpoints.                  |
