Document Purchasing API Webhook notifications
The Document Purchase API delivers document status changes to your webhook URL. A single order containing multiple documents can produce multiple webhook events.
Endpoint Requirements
Your webhook endpoint must:
- Use HTTPS
- Be publicly accessible
- Accept JSON
POSTrequests - Respond with
200 OKwithin 30 seconds - Verify HMAC-SHA256 signatures
Subscribe
curl -X POST "https://api.nimbusmaps.co.uk/docs/v1/subscribe" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-domain.com/webhooks/nimbus-documents"
}'
The response includes a secret. Store it immediately; it is returned only once and is required for signature verification.
Event Payload
{
"eventId": "88867097-4322-436e-ac1a-435e1bd17a15",
"eventType": "document.status_changed",
"timestamp": "2026-01-15T14:34:52Z",
"data": {
"reference": "11edd5d5-3615-4c59-9539-01bd7bb2cfe0",
"titleNumber": "AB123456",
"documentDescription": "Official Copy of Title Register",
"previousStatus": 1,
"newStatus": 2,
"statusDescription": "Completed",
"message": null,
"downloadUrl": "/Lookup/DownloadDocument?userDocumentReference=11edd5d5-3615-4c59-9539-01bd7bb2cfe0"
}
}
Use data.reference as the {document_id} when calling GET /download/{document_id}.
Signature Verification
Webhook requests include:
X-Webhook-Signature: BASE64_HMAC_SHA256_SIGNATURE
X-Webhook-Event: document.status_changed
X-Webhook-Id: UNIQUE_EVENT_ID
To verify a signature:
- Read the raw request body before JSON parsing.
- Compute HMAC-SHA256 over the raw body using the subscription secret.
- Base64-encode the digest.
- Compare it with
X-Webhook-Signatureusing a constant-time comparison.
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signature, secret) {
if (!signature) return false;
const expectedHash = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('base64');
const expected = Buffer.from(expectedHash);
const provided = Buffer.from(signature);
if (expected.length !== provided.length) return false;
return crypto.timingSafeEqual(provided, expected);
}
Delivery Operations
Use the webhook audit endpoints to investigate delivery:
GET /webhooks/auditGET /webhooks/events/{event_id}GET /webhooks/statistics