Receive webhooks¶
When to use this¶
Use webhooks instead of polling whenever your service can accept inbound HTTPS calls. Docmation invokes your URL once a work item reaches a terminal state (Finished or Faulted); you then call GetResult to fetch the actual payload. Webhooks are the preferred completion signal — polling exists as a fallback.
Prerequisites¶
- A public HTTPS endpoint that accepts an HTTP
GETwith no body, returns a2xxquickly, and is idempotent. - A
webhookUrlvalue on eachAddWorkItem*submission. The URL may contain the literal{0}placeholder — Docmation replaces it with theworkItemIdbefore calling, so you can route the request without parsing query strings.
Walkthrough¶
1. Register the URL on submit¶
Every AddWorkItem* request (see Submit a MAD batch, Submit a DOCOM batch, Submit an NVWA batch) accepts a webhookUrl on the BaseWorkItem:
{
"customerReference": "ORDER-2026-0001",
"documentReference": null,
"webhookUrl": "https://example.com/docmation/webhook/{0}",
"...": "..."
}
Use {0} in the path so the work-item id is part of the URL the receiver sees.
2. Receive the call¶
Docmation makes a single GET to the rendered URL. There is no request body and no signed payload — the URL itself (containing {0} → workItemId) is the entire signal. A minimal receiver:
Your handler should:
- Parse the
workItemIdfrom the path. - Acknowledge quickly with
200 OK(any 2xx works —200,201,204). - Asynchronously call back into Docmation to fetch the actual result, e.g.
GET /api/VlmMad/GetResult?workItemId=67890.
3. Fetch the result and mark it consumed¶
curl "https://api.docmation.eu/api/VlmMad/GetResult?workItemId=67890" \
-H "Authorization: Bearer <jwt>"
Once Docmation observes that the result has been fetched (ResultFetched is stamped), it stops calling the webhook even if some retries remain on the counter.
Retry & delivery semantics¶
Webhook delivery is driven by WebhookService, which runs as a cron job every 3 minutes (CronJobs.CallWebhooks). Each work item carries a WebhookCallCount budget (default from AppSettings.WebhookRetryCount, currently 9):
- Both transient network failures and non-2xx HTTP responses (4xx and 5xx alike) are treated the same — they decrement the counter and schedule a retry.
- After a failed attempt, the next is scheduled at
(maxRetryCount − WebhookCallCount)² × 30seconds using the pre-decrement value ofWebhookCallCount. With the defaultWebhookRetryCount = 9, the total budget across 9 attempts is roughly 1 h 42 min. - A successful
2xxflipsWebhookCallSuccessfultotrueand stops further attempts. - If the budget is exhausted before a success, Docmation gives up. The work item itself is unaffected —
GetResultwill still serve the data.
Backoff schedule (with the default WebhookRetryCount = 9)¶
| Attempt | WebhookCallCount going in |
Delay until next attempt | Cumulative wall-clock |
|---|---|---|---|
| 1 | 9 | (9-9)² × 30 = 0 s |
0 s |
| 2 | 8 | (9-8)² × 30 = 30 s |
30 s |
| 3 | 7 | (9-7)² × 30 = 120 s |
2 min 30 s |
| 4 | 6 | (9-6)² × 30 = 270 s |
7 min |
| 5 | 5 | (9-5)² × 30 = 480 s |
15 min |
| 6 | 4 | (9-4)² × 30 = 750 s |
27 min 30 s |
| 7 | 3 | (9-3)² × 30 = 1080 s |
45 min 30 s |
| 8 | 2 | (9-2)² × 30 = 1470 s |
1 h 10 min |
| 9 | 1 | (9-1)² × 30 = 1920 s |
1 h 42 min |
| — | 0 | (loop drops the row; no further attempts) | — |
The actual call only fires when the cron job runs (every 3 min) after the scheduled time, so delays above are a floor.
What to watch for¶
GET, notPOST— the webhook is a plainGETagainst the rendered URL. Do not configure your endpoint to require a body or signed payload.- Idempotency is your responsibility — Docmation may call the same
workItemIdmore than once (replay after a non-2xx). Accept duplicates as no-ops. - Respond quickly — slow handlers risk timing out and triggering a retry. Acknowledge first, work later.
- Invalid URLs are not retried indefinitely — if
string.Format(workItemUrl, workItemId)fails to parse as an absolutehttp(s)://URI, the service logs a warning and decrements the retry counter the same way as a failed HTTP call. - No payload means no signature — there is no HMAC or shared secret today; restrict access by URL knowledge (treat the URL as a capability) or by IP-allow-listing Docmation's outbound range. Plan to add a shared secret in v2 if you need stronger authentication.
- Develop locally — in
DEBUGbuilds the WebhookClient redirects non-localhostURLs tohttps://httpbin.org/getto prevent accidental production calls during development. This is a build-time guard, not a configurable runtime setting. - Consistency with the errors & retries reference page — same retry semantics described in one place, in case you spot a discrepancy.
AI-drafted from
WebhookService.cs. Verify field names against the live Swagger UI before publishing.