[{"data":1,"prerenderedAt":309},["ShallowReactive",2],{"docs-navigation":3,"doc-\u002Fdocs\u002Fwebhooks":60},[4,8,12,16,20,24,28,32,36,40,44,48,52,56],{"path":5,"title":6,"description":7},"\u002Fdocs\u002Fquickstart","Quickstart","Read both sides of an INE from your backend and receive structured JSON.",{"path":9,"title":10,"description":11},"\u002Fdocs\u002Fauthentication","Authentication","Keep company API keys on the server and separate them from dashboard access.",{"path":13,"title":14,"description":15},"\u002Fdocs\u002Fcreate-reading","Create a reading","Submit one front and back pair with a stable idempotency key.",{"path":17,"title":18,"description":19},"\u002Fdocs\u002Fretrieve-result","Retrieve a result","Read an existing job without repeating extraction or consuming another unit.",{"path":21,"title":22,"description":23},"\u002Fdocs\u002Fresponse-fields","Response fields","Choose the standard or extended response and use literal fields with review warnings.",{"path":25,"title":26,"description":27},"\u002Fdocs\u002Ferrors-and-retries","Errors and retries","Recover from errors without accidentally creating another charged reading.",{"path":29,"title":30,"description":31},"\u002Fdocs\u002Flimits-and-billing","Limits and billing","Plan allowances, shared admission limits and how reading units are counted.",{"path":33,"title":34,"description":35},"\u002Fdocs\u002Fprivacy-and-security","Privacy and security","Understand result retention, access controls and your backend's responsibilities.",{"path":37,"title":38,"description":39},"\u002Fdocs\u002Fexamples","Integration examples","Copyable server-side Node.js, Python and cURL examples with one POST per attempt.",{"path":41,"title":42,"description":43},"\u002Fdocs\u002Fdashboard","Dashboard usage","View your company's quota and request counts without exposing OCR data.",{"path":45,"title":46,"description":47},"\u002Fdocs\u002Fextended-reading","Extended extraction","Opt in to printed fields, separated address components, provenance and review checks.",{"path":49,"title":50,"description":51},"\u002Fdocs\u002Fwebhooks","Completion webhooks","Receive signed completion events without exposing OCR data in callbacks.",{"path":53,"title":54,"description":55},"\u002Fdocs\u002Fevaluation","Evaluation and limitations","Measured illustration results, remaining errors, and the limits of the extended profile.",{"path":57,"title":58,"description":59},"\u002Fdocs\u002Faddress-parts","Address parts","Use separate address inputs while retaining literal OCR and exact text sources.",{"id":61,"title":50,"body":62,"description":51,"extension":302,"meta":303,"navigation":304,"path":49,"seo":306,"stem":307,"__hash__":308},"docs\u002Fdocs\u002F12.webhooks.md",{"type":63,"value":64,"toc":297},"minimark",[65,74,77,82,198,212,216,235,275,283,287,290,293],[66,67,68,69,73],"p",{},"Contact us to configure an HTTPS callback for your company. Endpoints are approved individually; provisioning is manual. You receive a private ",[70,71,72],"code",{},"whsec_…"," signing secret. Keep it on your backend, separate from your API key. The operator must enable your exact hostname before delivery is available.",[66,75,76],{},"Webhooks report terminal job state. The initial OCR POST still waits for its result. This feature does not turn the OCR request into a durable background job or remove concurrency limits. GET and exact replay remain available for recovery.",[78,79,81],"h2",{"id":80},"event","Event",[83,84,89],"pre",{"className":85,"code":86,"language":87,"meta":88,"style":88},"language-json shiki shiki-themes material-theme-lighter github-light github-light","{\n  \"event_id\": \"a-unique-event-id\",\n  \"request_id\": \"the-original-request-id\",\n  \"status\": \"succeeded\",\n  \"expires_at\": \"2026-10-01T12:00:00.000Z\"\n}\n","json","",[70,90,91,100,130,151,172,192],{"__ignoreMap":88},[92,93,96],"span",{"class":94,"line":95},"line",1,[92,97,99],{"class":98},"sYEpm","{\n",[92,101,103,107,111,114,117,121,125,127],{"class":94,"line":102},2,[92,104,106],{"class":105},"s4hL5","  \"",[92,108,110],{"class":109},"sup7M","event_id",[92,112,113],{"class":105},"\"",[92,115,116],{"class":98},":",[92,118,120],{"class":119},"sU42L"," \"",[92,122,124],{"class":123},"sN0tt","a-unique-event-id",[92,126,113],{"class":119},[92,128,129],{"class":98},",\n",[92,131,133,135,138,140,142,144,147,149],{"class":94,"line":132},3,[92,134,106],{"class":105},[92,136,137],{"class":109},"request_id",[92,139,113],{"class":105},[92,141,116],{"class":98},[92,143,120],{"class":119},[92,145,146],{"class":123},"the-original-request-id",[92,148,113],{"class":119},[92,150,129],{"class":98},[92,152,154,156,159,161,163,165,168,170],{"class":94,"line":153},4,[92,155,106],{"class":105},[92,157,158],{"class":109},"status",[92,160,113],{"class":105},[92,162,116],{"class":98},[92,164,120],{"class":119},[92,166,167],{"class":123},"succeeded",[92,169,113],{"class":119},[92,171,129],{"class":98},[92,173,175,177,180,182,184,186,189],{"class":94,"line":174},5,[92,176,106],{"class":105},[92,178,179],{"class":109},"expires_at",[92,181,113],{"class":105},[92,183,116],{"class":98},[92,185,120],{"class":119},[92,187,188],{"class":123},"2026-10-01T12:00:00.000Z",[92,190,191],{"class":119},"\"\n",[92,193,195],{"class":94,"line":194},6,[92,196,197],{"class":98},"}\n",[66,199,200,201,203,204,207,208,211],{},"Status is ",[70,202,167],{}," or ",[70,205,206],{},"failed",". Events contain no photographs, OCR fields, API keys or provider error payloads. Retrieve the result from ",[70,209,210],{},"\u002Fapi\u002Fv3\u002Fine\u002F{request_id}"," with the owning API key before its expiration.",[78,213,215],{"id":214},"verify-before-processing","Verify before processing",[66,217,218,219,222,223,226,227,230,231,234],{},"The request includes ",[70,220,221],{},"X-INE-Event-ID",", ",[70,224,225],{},"X-INE-Timestamp"," (Unix seconds) and ",[70,228,229],{},"X-INE-Signature"," (",[70,232,233],{},"v1="," followed by a hexadecimal HMAC).",[236,237,238,242,245,256,262],"ol",{},[239,240,241],"li",{},"Read the exact raw request body before JSON parsing.",[239,243,244],{},"Reject a timestamp more than five minutes from your server clock.",[239,246,247,248,251,252,255],{},"Compute HMAC-SHA256 over ",[70,249,250],{},"timestamp + \".\" + rawBody"," using the full UTF-8 signing-secret string, including ",[70,253,254],{},"whsec_",". Do not base64-decode the secret.",[239,257,258,259,261],{},"Compare signatures in constant time and confirm the event header matches ",[70,260,110],{}," in the body.",[239,263,264,265,267,268,271,272,274],{},"Persist ",[70,266,110],{}," with a uniqueness constraint, schedule your processing, and return ",[70,269,270],{},"2xx"," promptly. A duplicate should also return ",[70,273,270],{},".",[66,276,277,282],{},[278,279,281],"a",{"href":280},"\u002Fwebhook-node.mjs","Download the Node.js verification helper",". It verifies the signature and timestamp; your database still needs to handle deduplication.",[78,284,286],{"id":285},"delivery-and-recovery","Delivery and recovery",[66,288,289],{},"Delivery is at least once. A minute scheduler retries failed deliveries with bounded backoff, up to six total attempts and no later than result expiration. Requests time out after five seconds and redirects are not followed. A callback may arrive after you have already received the successful POST response. A persisted event may be retried after an uncertain acknowledgement; deduplicate it.",[66,291,292],{},"Use GET to recover a result even if your webhook endpoint is unavailable. Rotating or revoking the webhook configuration cancels pending events for the old configuration; an already in-flight request may still finish. Do not treat a webhook as proof of identity or authenticity.",[294,295,296],"style",{},"html pre.shiki code .sYEpm, html code.shiki .sYEpm{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#24292E}html pre.shiki code .s4hL5, html code.shiki .s4hL5{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#005CC5}html pre.shiki code .sup7M, html code.shiki .sup7M{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#005CC5}html pre.shiki code .sU42L, html code.shiki .sU42L{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#032F62}html pre.shiki code .sN0tt, html code.shiki .sN0tt{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#032F62}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":88,"searchDepth":102,"depth":102,"links":298},[299,300,301],{"id":80,"depth":102,"text":81},{"id":214,"depth":102,"text":215},{"id":285,"depth":102,"text":286},"md",{},{"title":305},"Webhooks",{"title":50,"description":51},"docs\u002F12.webhooks","TDsC6JQJH57EXmn8H0hQxK5M_wyLuhfksX8Klrcs90U",1790659707387]