Webhooks API
Base URL: https://qck.sh/public-api/v1
List webhooks
Section titled “List webhooks”GET /webhooksPermission: webhooks:read
Response 200
{ "success": true, "data": [ { "id": "0190a8b2-7c3e-7d44-9f1a-2b3c4d5e6f70", "url": "https://your-server.com/webhook", "events": ["link.created", "link.updated"], "is_active": true, "consecutive_failures": 0, "created_at": "2026-04-01T10:00:00Z" } ]}Create a webhook
Section titled “Create a webhook”POST /webhooks| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Endpoint URL (HTTPS) |
events | string[] | Yes | Event types to subscribe to |
description | string | No | Description |
Permission: webhooks:write
Response 201: includes a secret field for signature verification (shown only once).
Event types
Section titled “Event types”| Event | Trigger |
|---|---|
link.created | Link created |
link.updated | Link updated |
link.deleted | Link deleted |
link.expired | Link expired (defined but not currently emitted) |
domain.verified | Domain DNS verified |
domain.expired | Domain verification expired (defined but not currently emitted) |
domain.suspended | Domain suspended |
api_key.created | API key created |
api_key.revoked | API key revoked |
team.member_added | Team member added |
team.member_removed | Team member removed |
subscription.upgraded | Tier upgraded |
subscription.downgraded | Tier downgraded |
bulk_import.completed | Bulk import finished |
conversion | Conversion tracked |
Get a webhook
Section titled “Get a webhook”GET /webhooks/{id}Permission: webhooks:read
Update a webhook
Section titled “Update a webhook”PATCH /webhooks/{id}| Field | Type | Description |
|---|---|---|
url | string | New endpoint URL |
events | string[] | Replace subscribed events |
description | string | New description |
is_active | boolean | Enable/disable |
Permission: webhooks:write
Delete a webhook
Section titled “Delete a webhook”DELETE /webhooks/{id}Permission: webhooks:write
Test a webhook
Section titled “Test a webhook”POST /webhooks/{id}/testSends a test payload to your endpoint.
Permission: webhooks:write
List deliveries
Section titled “List deliveries”GET /webhooks/{id}/deliveriesReturns the 50 most recent deliveries for the endpoint, newest first. There is no pagination.
Response 200
{ "success": true, "data": [ { "id": "0190a8b2-9d1f-7e55-8a2b-3c4d5e6f7a81", "endpoint_id": "0190a8b2-7c3e-7d44-9f1a-2b3c4d5e6f70", "event_type": "link.created", "payload": { "event": "link.created", "timestamp": "2026-04-08T10:00:00Z", "data": { } }, "status": "delivered", "attempt_number": 1, "max_attempts": 3, "http_status": 200, "response_body": "ok", "error_message": null, "next_retry_at": null, "created_at": "2026-04-08T10:00:00Z", "delivered_at": "2026-04-08T10:00:01Z" } ]}status is one of pending, delivered, failed, or retrying.
Permission: webhooks:read
Payload format
Section titled “Payload format”Your endpoint receives:
{ "event": "link.created", "timestamp": "2026-04-08T12:00:00Z", "data": { ... }}Signature verification
Section titled “Signature verification”Every delivery includes:
| Header | Description |
|---|---|
X-QCK-Signature | sha256=<hex>: HMAC-SHA256 of the raw request body, keyed with the endpoint secret |
X-QCK-Event | Event type |
X-QCK-Delivery | Delivery ID |
Compute HMAC-SHA256 over the raw body with your endpoint secret (returned once at creation) and compare it to the hex digest in X-QCK-Signature.
Failed deliveries are retried up to 3 attempts with exponential backoff (30s, 120s, 480s). Endpoints are auto-disabled after 10 consecutive failures.
Limits by tier
Section titled “Limits by tier”| Tier | Endpoints |
|---|---|
| Free | 1 |
| Basic ($19/mo) | 2 |
| Growth ($49/mo) | 5 |
| Pro ($99/mo) | 10 |
| Business ($249/mo) | 25 |