webhook-id and make handlers idempotent. Return 2xx quickly and move heavy work to a background queue. InkLink’s HTTP timeouts, fixed retry schedule, and API permission rules are documented below.
What you receive
Notifications are thin payloads: they include the inquiry and subject identifiers so your server can load full results via the existing KYC or Web inquiry APIs when needed.Event types
Eachtype uses the form kyc.result.<status> or web.result.<status>.
type | When it fires |
|---|---|
kyc.result.pending | KYC inquiry is waiting to be completed |
kyc.result.manual_review | Outcome needs manual review |
kyc.result.approved | KYC approved |
kyc.result.rejected | KYC rejected |
kyc.result.failed | KYC failed (technical or policy) |
web.result.pending | Web inquiry pending |
web.result.manual_review | Outcome needs manual review |
web.result.approved | Web inquiry approved |
web.result.rejected | Web inquiry rejected |
web.result.failed | Web inquiry failed |
Example payload
Inbound request shape
When an event matches one of your endpoint’s subscribedevent_types, InkLink issues an HTTP POST to your URL with:
| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | InkLink-Webhooks/1.0 |
webhook-id | Stable id for this event (prefix wh_evt_…). Use for idempotency. |
webhook-timestamp | Unix time (seconds) when the request was signed, as a decimal string. |
webhook-signature | Standard Webhooks form: v1,<base64(HMAC-SHA256)> |
fetch uses redirect: manual). Treat any non-2xx response, including 3xx, as a failed delivery.
Verifying signatures
Keep your endpoint’s signingsecret (prefix whsec_) on the server only. It is returned once when you create an endpoint or rotate the secret.
Using a Standard Webhooks library
The Standard Webhooks ecosystem includes maintained reference implementations for many languages (Python, JavaScript/TypeScript, Go, Rust, and others). Prefer one of these: you pass the raw request body and the webhook headers, and the library verifies the signature (and usually enforces a timestamp tolerance). For Node.js, installstandardwebhooks from npm (library source). The Webhook constructor takes the base64 key only–use the part of your InkLink secret after the whsec_ prefix as base64_secret. webhook_payload must be the raw body string (before JSON parsing); webhook_headers must include webhook-id, webhook-timestamp, and webhook-signature.
Manual verification (Node.js example)
Use this section if you are not using a library and need the exact signing procedure. Signing string (must use the exact raw request body bytes):webhook_id– value of thewebhook-idheaderwebhook_timestamp– value of thewebhook-timestampheader (string)payload– raw JSON body as a string
whsec_), Base64-encode the digest, and compare to the v1,… entry in webhook-signature using a constant-time comparison.
Reliability and delivery attempts
Respond with 2xx quickly and offload heavy work to a background queue. InkLink records whether each HTTP attempt succeeded (status 200–299). Retries are not “wait after failure then backoff.” Each delivery uses five fixed time slots measured from that delivery’s creation time (wall-clock):| Attempt | Earliest time after delivery is created |
|---|---|
| 1 | 0 s |
| 2 | 30 s |
| 3 | 90 s |
| 4 | 270 s (4 min 30 s) |
| 5 | 720 s (12 min) |
webhook-id. Design handlers so duplicate deliveries (for example after a slow 2xx or overlapping workers) are safe.
Managing endpoints (API)
Use your organization’s API key on every call (Authentication). Programmatic routes:- List webhook endpoints –
GET /webhook/endpoints - Create webhook endpoint –
POST /webhook/endpoints(returnssecretonce) - Get webhook endpoint –
GET /webhook/endpoints/{id} - Update webhook endpoint –
PATCH /webhook/endpoints/{id} - Delete webhook endpoint –
DELETE /webhook/endpoints/{id} - Rotate webhook signing secret –
POST /webhook/endpoints/{id}/rotate-secret
INTERNAL_ERROR and a clear message (see Error handling). Listing and fetching endpoints is available to authenticated organization members.