Skip to main content
Webhooks send HTTP POST requests to your server whenever specific events occur in Quikly. Use them to sync with your CRM, trigger n8n workflows, send Slack notifications, or build custom automations.

Create a webhook

You can create webhooks from the Quikly UI or through the API.

From the UI

Go to Settings → Webhooks and click Create Webhook. Enter a name, your endpoint URL, and select the events you want to subscribe to.

From the API

curl -X POST "https://api.getquikly.com/api/external/v1/webhooks" \
  -H "X-API-Key: qk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM sync",
    "url": "https://your-server.com/webhooks/quikly",
    "events": ["proposal.created", "proposal.shared", "proposal.accepted"]
  }'
The response includes a secret field that is shown only once. Store it immediately — you need it to verify webhook signatures.

Available events

EventFires when
proposal.createdA new proposal is created
proposal.updatedA proposal is modified (requirements, settings, pricing)
proposal.sharedA proposal is shared with a client via link
proposal.acceptedA client accepts a proposal
proposal.rejectedA client rejects a proposal
proposal.revision_requestedA client requests changes to a proposal
lead_session.createdA new lead session starts (from widget, Telegram, or API)
lead_session.updatedA lead session status changes (e.g., gathering info → proposal ready)
You can subscribe to specific events or listen to all of them by including each event in the events array.

Payload format

Every webhook delivery sends a JSON payload with this structure:
{
  "event": "proposal.accepted",
  "timestamp": "2026-04-03T14:30:00Z",
  "webhook_id": "wh_abc123",
  "data": {
    "proposal_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Cloud Migration - Acme Corp",
    "status": "accepted",
    "client_name": "John Smith",
    "total": 24500.00,
    "currency": "USD",
    "share_url": "https://app.getquikly.com/p/abc123token",
    "responded_at": "2026-04-03T14:30:00Z"
  }
}
For lead_session events, the data object contains session fields like channel, channel_id, client_name, brief, and status.

HTTP headers

Each webhook request includes these headers:
HeaderDescription
X-Quikly-EventEvent type (e.g., proposal.accepted)
X-Quikly-SignatureHMAC-SHA256 hex digest of the request body
X-Quikly-TimestampUnix timestamp of when the webhook was sent
X-Quikly-Webhook-IdID of the webhook configuration
Content-TypeAlways application/json

Verify signatures

Every webhook is signed with the secret you received when creating it. Verify the X-Quikly-Signature header to confirm the request came from Quikly.
import hmac
import hashlib

def verify_webhook(payload_body: bytes, secret: str, signature: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        payload_body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)
Always verify signatures before processing webhook payloads. This prevents attackers from sending fake events to your endpoint.

Retry policy

If your endpoint returns a non-2xx status code or times out (10-second limit), Quikly retries the delivery with exponential backoff:
AttemptDelay
1st retry30 seconds
2nd retry2 minutes
3rd retry15 minutes
4th retry1 hour
5th retry4 hours
After 5 failed retries, the delivery is marked as failed. You can see all attempts in the webhook logs.

Test a webhook

Send a test event to verify your endpoint is reachable:
curl -X POST "https://api.getquikly.com/api/external/v1/webhooks/{webhook_id}/test" \
  -H "X-API-Key: qk_your_api_key_here"
The test payload uses the event type test and contains sample data. Your endpoint should return a 200 status code.

View delivery logs

Check recent deliveries and debug failures:
curl "https://api.getquikly.com/api/external/v1/webhooks/{webhook_id}/logs" \
  -H "X-API-Key: qk_your_api_key_here"
Each log entry includes the HTTP status code, response body, response time, and the full payload that was sent. You can also view logs in the Quikly UI under Settings → Webhooks → (select webhook) → Logs.

Managing webhooks

OperationAPI endpointUI path
List all webhooksGET /webhooksSettings → Webhooks
Update events or URLPUT /webhooks/{id}Click webhook → Edit
Pause deliveriesPUT /webhooks/{id} with is_active: falseToggle switch
DeleteDELETE /webhooks/{id}Click webhook → Delete
Regenerate secretPOST /webhooks/{id}/regenerate-secret (UI only)Click webhook → Regenerate