Manage webhook endpoints
All endpoint management routes require an authenticated full administrator and use application/vnd.api+json.
Endpoint lifecycle
Seção intitulada “Endpoint lifecycle”create or change URL → pending-verification → active ⇄ paused → deleted- New endpoints and changed URLs must pass verification before receiving production events.
- An active endpoint can be paused manually.
- Endpoints paused manually or for delivery health can be resumed if the current destination is still verified.
- A destination blocked by the security policy cannot be resumed directly. Change it to a valid public HTTPS URL and verify the new destination.
- Deletion is final. Undelivered work for that endpoint is suppressed and its secrets are cleared.
Events captured while an endpoint is pending or paused are not delivered when it later becomes active. Pausing, removing a subscription, changing a URL, or deleting an endpoint can suppress already-pending deliveries.
Endpoint routes
Seção intitulada “Endpoint routes”| Method | Path | Purpose |
|---|---|---|
GET |
/v1/webhook-endpoints |
List live endpoints. |
GET |
/v1/webhook-endpoints/:id |
Read one endpoint and its current ETag. |
POST |
/v1/webhook-endpoints |
Create an endpoint. |
PATCH |
/v1/webhook-endpoints/:id |
Change its name, subscriptions, URL, or status. |
DELETE |
/v1/webhook-endpoints/:id |
Delete an endpoint. |
POST |
/v1/webhook-endpoint-verifications |
Queue destination verification. |
POST |
/v1/webhook-endpoint-secret-rotations |
Rotate the signing secret. |
POST |
/v1/webhook-test-deliveries |
Queue a one-attempt test. |
Endpoint lists use page[number] and page[size]. The default page size is 25 and the maximum is 100.
Endpoint attributes
Seção intitulada “Endpoint attributes”| Attribute | Description |
|---|---|
name |
Optional display name, at most 120 characters. |
url |
HTTPS destination, at most 2,048 characters. Credentials and fragments are not allowed. DNS must resolve only to public addresses. |
events |
Non-empty, unique array of supported event types. |
status |
pending-verification, active, or paused. Deleted endpoints are not returned. |
effective-health |
pending-verification, paused, healthy, degraded, or failing. |
pause-reason |
manual, health, security-policy, or null. |
configuration-version |
Optimistic-concurrency version used by If-Match and verification. |
destination-version |
Increments when the URL changes. |
verified-destination-version |
Version most recently verified, or null. |
secret-generation |
Current signing-secret generation. |
verified-at |
Time the current destination was verified, or null. |
last-production-attempt-at |
Most recent production attempt time. |
last-production-success-at |
Most recent production success time. |
last-production-failure-at |
Most recent production failure time. |
consecutive-production-failures |
Current consecutive failure count. |
last-production-failure |
Diagnostic code and message, or null. |
metrics |
Separate rolling metrics for 24h and 7d, including attempts, retries, latency, and terminal success. |
created-at, updated-at |
Endpoint timestamps. |
Concurrency with ETag and If-Match
Seção intitulada “Concurrency with ETag and If-Match”GET /v1/webhook-endpoints/:id and successful endpoint writes return an ETag such as:
ETag: "webhook-endpoint-4"Every PATCH and DELETE must send the current value:
If-Match: "webhook-endpoint-4"A stale version returns 409 Conflict; a missing or malformed header returns 428 Precondition Required. Fetch the endpoint again before deciding whether to retry.
Update a name or subscriptions
Seção intitulada “Update a name or subscriptions”name and events can be changed together. Removing an event type suppresses pending deliveries for that removed subscription.
curl --request PATCH 'https://api.celula.in/v1/webhook-endpoints/ENDPOINT_ID' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ --header 'Content-Type: application/vnd.api+json' \ --header 'If-Match: "webhook-endpoint-4"' \ --data '{ "data": { "type": "webhook-endpoints", "attributes": { "name": "People synchronization", "events": ["person.created", "person.updated", "person.merged"] } } }'Pause or resume
Seção intitulada “Pause or resume”A status transition must be the only attribute in the request:
{ "data": { "type": "webhook-endpoints", "attributes": { "status": "paused" } }}Send the same shape with "status": "active" to resume an endpoint paused manually or for health. Both requests require the current If-Match value.
Change the destination URL
Seção intitulada “Change the destination URL”The API dispatches a URL reset based on the presence of attributes.url, not on whether its value changed. Any accepted PATCH that includes url—even the current URL or another value that normalizes to it—performs the complete destination reset described below. Omit url unless you intend to rotate the secret, suspend delivery, and verify the destination again. In particular, do not send a full stored endpoint representation when updating only name or events.
A PATCH containing url requires both If-Match and Idempotency-Key. It can include name and events in the same request.
curl --request PATCH 'https://api.celula.in/v1/webhook-endpoints/ENDPOINT_ID' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ --header 'Content-Type: application/vnd.api+json' \ --header 'If-Match: "webhook-endpoint-4"' \ --header 'Idempotency-Key: move-endpoint-to-v2' \ --data '{ "data": { "type": "webhook-endpoints", "attributes": { "url": "https://integrations.example.com/v2/webhooks/celulain" } } }'The update:
- moves the endpoint to
pending-verification; - increments its configuration, destination, and secret generations;
- suppresses undelivered requests for the old URL;
- invalidates the old secret immediately;
- returns the new secret once in
data.meta.secret.
Store the new secret and verify the destination again. Exact retries using the same idempotency key and request return the same result for 24 hours. Reusing the key with different input returns 409 Conflict.
Rotate a secret
Seção intitulada “Rotate a secret”Read the endpoint’s current secret-generation, then submit it with a unique idempotency key:
curl --request POST 'https://api.celula.in/v1/webhook-endpoint-secret-rotations' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ --header 'Content-Type: application/vnd.api+json' \ --header 'Idempotency-Key: rotate-production-secret-2026-08' \ --data '{ "data": { "type": "webhook-endpoint-secret-rotations", "attributes": { "secret-generation": 3 }, "relationships": { "endpoint": { "data": { "type": "webhook-endpoints", "id": "ENDPOINT_ID" } } } } }'The 201 Created response returns the new generation and new secret in data.meta.secret. Store it before discarding the response.
For the next 48 hours, requests contain signatures from both the new and previous secret. Deploy the new secret to your receiver, accept either secret during the overlap, and remove the old secret after the overlap ends. Another rotation for the endpoint is rejected while an overlap is active.
Idempotent replay is available for 24 hours. A successful replay with the same request returns the same secret; a mismatched or expired replay never exposes a secret.
Management action limits
Seção intitulada “Management action limits”| Action | Per account | Per endpoint | Window |
|---|---|---|---|
| Verification | 20 | 5 | 1 hour |
| Test delivery | 60 | 10 | 1 hour |
| Manual redelivery | 100 | 20 | 1 hour |
| Secret rotation | 10 | 1 | 48 hours |
Exceeding a limit returns 429 Too Many Requests. Outbound-triggering actions fail with 503 Service Unavailable if their action limiter is unavailable.
