Webhooks
Webhooks provide real-time notifications when events occur in your workspace. Instead of polling the API for changes, you configure endpoints that Colleckt delivers HTTP POST requests to when events happen.
Overview
Webhooks are useful for:
- Receiving notifications when a verification status changes
- Updating your internal systems when a decision is made
- Triggering downstream workflows (e.g., sending emails, updating databases)
- Logging verification activity in your own systems
Webhook Events
The following events can trigger a webhook delivery:
| Event | Code | When It Fires |
|---|---|---|
| Verification Started | verification.started | A new verification is created |
| Verification Submitted | verification.submitted | A verification is submitted for processing |
| Verification Finished | verification.finished | A verification reaches a final decision (approved, rejected, or double-check) |
| Verification Canceled | verification.canceled | A verification is canceled |
| Document Uploaded | document.uploaded | A document image is uploaded |
| Document Canceled | document.canceled | A document is canceled |
| Decision Made | decision.made | A decision (approve/reject/double-check) is made on a document |
| Decision Canceled | decision.canceled | A decision is canceled |
Creating a Webhook
- Navigate to Webhooks in the workspace dashboard
- Click New Webhook
- Configure the following:
| Field | Required | Description |
|---|---|---|
| URL | Yes | The endpoint URL that will receive webhook payloads (HTTPS only) |
| Events | Yes | One or more events to subscribe to |
| SSL Verification | No | Enable/disable SSL certificate verification (enabled by default) |
| Active | No | Enable/disable the webhook without deleting it |
Signing Secret
When a webhook is created, a unique signing secret is auto-generated:
- The secret is displayed only once at creation time
- Store it securely — you will need it to verify webhook payloads
- The secret is hashed in our system and cannot be retrieved later
- Signing secrets are 64-character random strings
Authentication
You can configure an authentication header that will be sent with every webhook request. This is useful for API key-based authentication on your endpoint.
Webhook Delivery
Delivery Format
Each webhook is delivered as an HTTP POST request with:
- Content-Type:
application/json - Signature:
Signatureheader containing HMAC-SHA256 hash of the payload
Payload Structure
{
"data": {
"id": "ver_xxxxx",
"url": "https://{workspace}.colleckt.io/spa/v3/.../process",
"flow": "usps-1583",
"qr_code": "https://{workspace}.colleckt.io/qr/...",
"comments": [],
"documents": [],
"created_at": "2026-06-14T02:14:13.000000Z",
"updated_at": "2026-06-14T02:14:13.000000Z",
"status_label": "Started",
"vendor_state": "Wyoming",
"expected_data": {
"person": {
"first_name": "Homer",
"last_name": "Simpson",
"date_of_birth": ""
},
"address": {
"street": "742 Evergreen Terrace",
"city": "Springfield",
"state": "Tennessee",
"postal_code": "92026",
"country": "USA"
},
"documents": {
"photo_id": {
"type": "Passport",
"number": "AB123456",
"country": "USA"
},
"proof_of_address": {
"type": "Driver License",
"number": "",
"country": "USA"
}
}
},
"extracted_data": [],
"vendor_reference": "225050996948"
},
"event": "verification.started"
}Retry Logic
If your endpoint does not return a 2xx status code, the webhook is retried:
- Retries follow an exponential backoff schedule
- Failed deliveries are logged in the Webhook Logs section
- Each log entry shows the request payload, response status, and error message
Verifying Webhook Signatures
Each webhook request includes a Signature header. You should verify this signature to confirm the request came from Colleckt:
Signature: {base64_encoded_hmac_sha256_signature}The signature is computed as:
HMAC-SHA256(payload_body, signing_secret)Verification Example
const crypto = require('crypto');
function verifyWebhookSignature(payloadBody, signature, signingSecret) {
const expectedSignature = crypto
.createHmac('sha256', signingSecret)
.update(payloadBody)
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}function verifyWebhookSignature(string $payloadBody, string $signature, string $signingSecret): bool {
$expectedSignature = hash_hmac('sha256', $payloadBody, $signingSecret, true);
return hash_equals(
base64_decode($signature),
$expectedSignature
);
}Managing Webhooks
View Webhooks
The webhooks list shows all configured webhooks with their status (active/inactive), URL, and associated events.
Update Webhook
You can modify a webhook's URL, events, authentication, and SSL verification settings. The signing secret cannot be changed — create a new webhook if a new secret is needed.
Delete Webhook
Deleting a webhook removes it permanently. All undelivered events for this webhook will be discarded.
Rate Limits
Webhooks are delivered with best-effort timing. There is no guaranteed delivery SLA, but the system aims for near-real-time delivery. Very high volumes of verification activity may result in slight delivery delays.
Best Practices
- Respond quickly — Your endpoint should return a 2xx status within a reasonable timeout
- Handle duplicates — Webhook delivery is at-least-once; you may receive the same event multiple times
- Verify signatures — Always verify the signature to ensure the request is genuine
- Process asynchronously — Don't perform long-running operations in your webhook handler; queue them for later processing
- Log all deliveries — Keep a record of webhook events for debugging and audit purposes
- Use the sandbox — Test your webhook integration in the sandbox environment before going live
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Endpoint unreachable | Network error or DNS issue | Verify the URL is accessible from the internet |
| Invalid signature | Wrong signing secret or payload encoding | Verify the secret and ensure raw payload is used for HMAC |
| SSL verification failed | Invalid or self-signed certificate | Use a valid SSL certificate or disable SSL verification (not recommended) |
| Timeout | Endpoint too slow to respond | Optimize your endpoint to return 2xx within 30 seconds |
| 4xx/5xx response | Application error on your end | Check your application logs for the cause |