# Webhook Endpoints (outbound) Manage destinations that receive event notifications from the CRM. Each endpoint subscribes to one or more event names; events are delivered as signed HTTPS POST requests (see the **Webhooks & Public Tracking** appendix at the bottom of this page for the envelope, signature scheme, and retry policy). The `secret` is auto-generated on create and is the HMAC-SHA256 key used to sign every delivery. Treat it like a password — it is returned only on the initial create response and on `show`; rotate by deleting and recreating. ## List webhook endpoints `GET /api/webhook-endpoints` Lists the webhook endpoints this account has registered, newest first, with the events each one is subscribed to and whether it is active. Call it before registering another one: duplicated endpoints are the usual reason somebody receives the same event twice and blames the retry policy. Secrets are never included — they are shown once, at creation. ### Query parameters - `location_id` (integer) — Scope to a location. - `is_active` (boolean) — Filter active vs disabled. - `per_page` (integer) — Rows per page. Default 20, maximum 100. See [Lists, paging and filters](#lists-paging-and-filters). ### Example request ```bash curl --request GET \ --get "https://klozzo.com/api/webhook-endpoints?location_id=1&is_active=1&per_page=20" \ --header "Authorization: Bearer {YOUR_API_TOKEN}" \ --header "Content-Type: application/json" \ --header "Accept: application/json" ``` ### Response `200` ```json { "data": [ { "id": null, "location_id": null, "url": "https://example.test/webhooks/9MTvekde", "events": [ "contact.created", "message.received" ], "is_active": true, "last_delivery_at": null, "created_at": null, "updated_at": null }, { "id": null, "location_id": null, "url": "https://example.test/webhooks/KcUoSJav", "events": [ "contact.created", "message.received" ], "is_active": true, "last_delivery_at": null, "created_at": null, "updated_at": null } ], "links": { "first": "/?page=1", "last": "/?page=1", "prev": null, "next": null }, "meta": { "current_page": 1, "from": 1, "last_page": 1, "links": [ { "url": null, "label": "« Previous", "page": null, "active": false }, { "url": "/?page=1", "label": "1", "page": 1, "active": true }, { "url": null, "label": "Next »", "page": null, "active": false } ], "path": "/", "per_page": 20, "to": 2, "total": 2 } } ``` ## Register a webhook endpoint `POST /api/webhook-endpoints` Returns the new endpoint including a freshly generated `secret`. **Save this secret immediately**: it is only returned on this create call and on subsequent `show`/`index` calls if the endpoint is still active. ### Body parameters - `location_id` (integer) — Scope to a location. - `url` (string, required) — HTTPS URL that will receive POST deliveries (max 2048 chars). - `events` (string[], required) — Event names this endpoint subscribes to. At least one. - `is_active` (boolean) — Default true. ### Example request ```bash curl --request POST \ "https://klozzo.com/api/webhook-endpoints" \ --header "Authorization: Bearer {YOUR_API_TOKEN}" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --data "{ \"location_id\": 1, \"url\": \"https:\\/\\/hooks.example.com\\/herd\", \"events\": [ \"contact.created\", \"contact.updated\" ], \"is_active\": true }" ``` ### Response `200` ```json { "data": { "id": null, "location_id": null, "url": "https://example.test/webhooks/tP7QtxDt", "events": [ "contact.created", "message.received" ], "is_active": true, "last_delivery_at": null, "created_at": null, "updated_at": null, "secret": "nHsIVY0AexDAbMktLudb8xsq6Ofw0OXkmU7NjPL1" } } ``` ### Response `422` — Not a URL ```json { "message": "Url no es una dirección web válida.", "errors": { "url": [ "Url no es una dirección web válida." ] } } ``` ### Response `422` — An event name that does not exist ```json { "message": "Events.0 no es una opción válida.", "errors": { "events.0": [ "Events.0 no es una opción válida." ] } } ``` ## Fetch a webhook endpoint `GET /api/webhook-endpoints/{webhookEndpoint_id}` Returns one webhook endpoint by id: its URL, the events it is subscribed to and whether it is active. **The signing secret is not returned here** — it is shown once, when the endpoint is created. If you lost it, delete the endpoint and register it again; there is no way to read it back, which is the point. To see what has actually been delivered, use `GET /api/webhook-endpoints/{id}/deliveries`. ### Path parameters - `webhookEndpoint_id` (integer, required) — Endpoint ID. ### Example request ```bash curl --request GET \ --get "https://klozzo.com/api/webhook-endpoints/6" \ --header "Authorization: Bearer {YOUR_API_TOKEN}" \ --header "Content-Type: application/json" \ --header "Accept: application/json" ``` ### Response `200` ```json { "data": { "id": null, "location_id": null, "url": "https://example.test/webhooks/Mh00hWJg", "events": [ "contact.created", "message.received" ], "is_active": true, "last_delivery_at": null, "created_at": null, "updated_at": null } } ``` ### Response `404` — Does not exist, or belongs to another location ```json { "message": "No query results for model." } ``` ## Update a webhook endpoint `PATCH /api/webhook-endpoints/{webhookEndpoint_id}` Updates a webhook endpoint by id, changing only the fields you send. To rotate the signing secret, delete and recreate. ### Path parameters - `webhookEndpoint_id` (integer, required) — Endpoint ID. ### Body parameters - `url` (string) — HTTPS URL (max 2048 chars). - `events` (string[]) — Subscribed event names. - `is_active` (boolean) — Pause without deleting. ### Example request ```bash curl --request PATCH \ "https://klozzo.com/api/webhook-endpoints/6" \ --header "Authorization: Bearer {YOUR_API_TOKEN}" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --data "{ \"url\": \"https:\\/\\/hooks.example.com\\/herd\", \"events\": [ \"architecto\" ], \"is_active\": false }" ``` ### Response `200` ```json { "data": { "id": null, "location_id": null, "url": "https://example.test/webhooks/USS1QLNW", "events": [ "contact.created", "message.received" ], "is_active": true, "last_delivery_at": null, "created_at": null, "updated_at": null } } ``` ## Delete a webhook endpoint `DELETE /api/webhook-endpoints/{webhookEndpoint_id}` Removes the endpoint and invalidates its signing secret. Historical `WebhookDelivery` records remain for audit. ### Path parameters - `webhookEndpoint_id` (integer, required) — Endpoint ID. ### Example request ```bash curl --request DELETE \ "https://klozzo.com/api/webhook-endpoints/6" \ --header "Authorization: Bearer {YOUR_API_TOKEN}" \ --header "Content-Type: application/json" \ --header "Accept: application/json" ``` ### Response `200` ```json { "message": "Webhook endpoint deleted." } ``` ## List delivery attempts for an endpoint `GET /api/webhook-endpoints/{webhookEndpoint_id}/deliveries` Returns recent delivery attempts (one row per HTTP call, including retries), newest first. Useful for debugging non-2xx responses from your endpoint. ### Path parameters - `webhookEndpoint_id` (integer, required) — Endpoint ID. ### Query parameters - `per_page` (integer) — Rows per page. Default 20, maximum 100. See [Lists, paging and filters](#lists-paging-and-filters). ### Example request ```bash curl --request GET \ --get "https://klozzo.com/api/webhook-endpoints/6/deliveries?per_page=20" \ --header "Authorization: Bearer {YOUR_API_TOKEN}" \ --header "Content-Type: application/json" \ --header "Accept: application/json" ``` ### Response `200` ```json { "data": [ { "id": null, "endpoint_id": 229, "event_type": "contact.created", "response_status": null, "attempts": 0, "delivered_at": null, "created_at": null }, { "id": null, "endpoint_id": 230, "event_type": "contact.created", "response_status": null, "attempts": 0, "delivered_at": null, "created_at": null } ], "links": { "first": "/?page=1", "last": "/?page=1", "prev": null, "next": null }, "meta": { "current_page": 1, "from": 1, "last_page": 1, "links": [ { "url": null, "label": "« Previous", "page": null, "active": false }, { "url": "/?page=1", "label": "1", "page": 1, "active": true }, { "url": null, "label": "Next »", "page": null, "active": false } ], "path": "/", "per_page": 20, "to": 2, "total": 2 } } ```