Webhook Setup Guide
Configure webhooks to receive real-time notifications for document, shipment, and compliance events.
Overview
Webhooks let your systems (for example a TMS or ERP) react in real time as CargoLint processes documents and evaluates shipments. This guide walks through configuring, securing, testing, and monitoring webhooks.
Webhook access is available on Business and Enterprise plans. Managing webhooks requires an Owner or Admin account.
Creating a Webhook
Via the dashboard
- Navigate to Settings > Integrations > Webhooks
- Click Add Webhook
- Enter your endpoint URL (must use HTTPS)
- Select which events should trigger notifications
- Click Create Webhook
- Copy the signing secret shown on creation and store it securely - it is displayed only once
Via the API
curl -X POST https://api.cargolint.com/api/v1/webhooks \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.com/webhooks/cargolint",
"events": ["document.completed", "shipment.evaluated"]
}'
The create response includes a one-time secret field. Save it now - you will need it to verify signatures, and it cannot be retrieved later. If you lose it, rotate the secret.
Supported Events
Documents
document.uploaded- received and queued for processingdocument.pending_approval- extracted with high confidence; awaiting approvaldocument.requires_review- extracted with low confidence, or sent back by a shipment-consistency findingdocument.failed- extraction faileddocument.reviewed- a reviewer submitted correctionsdocument.completed- approved and finalizeddocument.generated- generated from another document (e.g. a packing list from an invoice)document.cloned- cloned from another documentdocument.skipped- deferred by a reviewer
Shipments
shipment.created- a new shipment was createdshipment.document_linked- a document was attached to a shipmentshipment.evaluated- cross-document consistency evaluation completed (includesoverallStatus)shipment.settled- a shipment was finalized
Compliance
compliance.completed- a single-document compliance check finished (includesoverallStatus)compliance.warning- deprecated; fires alongsidecompliance.completedonly onWarning/Error
See the Webhooks API reference for payload shapes and the full delivery contract.
Webhook Security
Each delivery is signed with HMAC-SHA256. The request includes these headers:
| Header | Purpose |
|---|---|
| X-CargoLint-Signature | v1={hex} signature |
| X-CargoLint-Timestamp | Unix timestamp used in the signature |
| X-CargoLint-Event | The event type |
| X-CargoLint-DeliveryId | Unique delivery id (use for idempotency) |
The signature is computed over "{timestamp}.{payload}". Your signing secret is base64-encoded - decode it to get the HMAC key:
import base64
import hashlib
import hmac
def verify_signature(payload: str, signature_header: str, timestamp_header: str, secret: str) -> bool:
signed = f"{timestamp_header}.{payload}".encode()
expected = hmac.new(
base64.b64decode(secret),
signed,
hashlib.sha256,
).hexdigest()
provided = signature_header.split("v1=", 1)[-1]
return hmac.compare_digest(expected, provided)
Security: Always use
hmac.compare_digest()(constant-time comparison) - never==, which is vulnerable to timing attacks. Also reject deliveries whose timestamp is far from the current time to prevent replay.
Rotating the Signing Secret
If a secret is lost or may be exposed, rotate it. Rotation returns a new secret once and immediately invalidates the old one, without affecting the webhook or its delivery history.
curl -X POST https://api.cargolint.com/api/v1/webhooks/{id}/rotate-secret \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Testing Your Webhook
- In the webhook settings, click Send Test Payload (delivers a
webhook.testevent) - Verify your endpoint returns HTTP 200
- Check the result in the delivery history
Monitoring Deliveries
The Delivery History shows, per attempt:
- Timestamp of the attempt
- Delivery status (
Pending,Success, orFailed) - Response status code
- Attempt count and last error
Retries and Failed Deliveries
A non-2xx response or network error is retried up to 3 attempts with a backoff of 5s, 15s, then 45s (each attempt times out after 10 seconds). After the final failed attempt the delivery is marked Failed. The webhook itself remains active - it is not automatically disabled, so subsequent events are still delivered.
Troubleshooting
Webhook not receiving events:
- Confirm the endpoint is publicly reachable over HTTPS
- Confirm the webhook is subscribed to the event you expect
- Check firewall/proxy configuration
- Review the delivery history for error messages
High failure rate:
- Return a 2xx response within 10 seconds; offload heavy work to a background job
- Check your server logs for connection or TLS errors