Overview
Creates a new webhook subscription. After creation, CleanLife will send a POST request to your specified URL whenever the subscribed events occur on bookings associated with your partner account.
The webhook secret is only returned once — in the response to this request. Store it securely. You cannot retrieve it again (only rotate it).
Endpoint
POST /partners/webhooks/subscriptions
Authentication
Requires a valid API Key with the partner_webhooks_manage permission.
Request Body
{
"url": "https://yourplatform.com/webhooks/cleanlife",
"events": [
"booking.created",
"booking.updated",
"booking.cancelled",
"booking.payment_confirmed",
"booking.appointment_status_changed"
]
}
| Field | Type | Required | Description |
|---|
url | string (URL) | Yes | Your HTTPS endpoint that will receive webhook deliveries. Must match your registered allowed domain. |
events | string[] | Yes | Array of event types to subscribe to. At least one event is required. |
Valid Event Values
| Value | Description |
|---|
booking.created | Fired when a booking is successfully created |
booking.updated | Fired when a booking is rescheduled or updated |
booking.cancelled | Fired when a booking is cancelled |
booking.payment_failed | Fired when async payment processing fails (CLEANOS responsibility) |
booking.payment_confirmed | Fired when a partner confirms payment (PARTNER responsibility) |
booking.appointment_status_changed | Fired when the service appointment status changes |
Example Request
curl -X POST "https://apiv3.thecleanlife.dev/v1/partners/webhooks/subscriptions" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourplatform.com/webhooks/cleanlife",
"events": ["booking.created", "booking.cancelled", "booking.appointment_status_changed"]
}'
Success Response
HTTP Status: 200 OK
{
"success": true,
"data": {
"id": "gggggggg-0000-0000-0000-000000000001",
"partnerClientId": "hhhhhhhh-0000-0000-0000-000000000001",
"url": "https://yourplatform.com/webhooks/cleanlife",
"events": ["booking.created", "booking.cancelled", "booking.appointment_status_changed"],
"secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"status": "ACTIVE",
"createdAt": "2026-06-15T10:00:00+03:00",
"updatedAt": "2026-06-15T10:00:00+03:00"
}
}
Critical: Save the secret field immediately. It is a 64-character hex string (32 random bytes). It will never be returned again after this response. If you lose it, you must rotate it.
Error Responses
| HTTP Status | Code | Description |
|---|
400 | VALIDATION_ERROR | Invalid URL, invalid event name, or URL does not match allowed domain |
400 | VALIDATION_ERROR (msg: “Webhook URL must use HTTPS”) | URL uses HTTP, not HTTPS |
400 | VALIDATION_ERROR (msg: “Webhook URL host is not allowed”) | URL points to a blocked/private host |
400 | VALIDATION_ERROR (msg: “Partner has no allowed webhook domains configured”) | Your partner account has no registered domains |
400 | VALIDATION_ERROR (msg: “Webhook domain is not allowed for this partner”) | URL hostname not in your allowed domains |
401 | UNAUTHORIZED | Missing or invalid API key |
403 | FORBIDDEN | Missing partner_webhooks_manage permission |
Notes
- You can create multiple subscriptions with different URLs and/or different event sets.
- A subscription is immediately
ACTIVE upon creation.
- If you need to change the subscribed events or URL later, use
PATCH /partners/webhooks/subscriptions/:id.
- Deleting a subscription stops future deliveries. Past delivery history remains available via
GET /partners/webhooks/deliveries.