{"componentChunkName":"component---src-templates-simple-markdown-js","path":"/docs/ai/document-ai/events-and-webhooks/","matchPath":"","result":{"data":{"markdownRemark":{"html":"<h1 style=\"position:relative;\"><a href=\"#document-events-and-webhooks\" aria-label=\"document events and webhooks permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"document-events-and-webhooks\"></div>Document Events and Webhooks</h1>\n<p>Subscribe to document lifecycle events when your integration should react without polling.</p>\n<p>Document AI publishes three versioned event types:</p>\n<ul>\n<li>\n<code class=\"language-text\">document.created.v1</code>\n</li>\n<li>\n<code class=\"language-text\">document.updated.v1</code>\n</li>\n<li>\n<code class=\"language-text\">document.deleted.v1</code>\n</li>\n</ul>\n<p>Processing completion, failure, skip, and oversize outcomes appear as document updates. There are no separate <code class=\"language-text\">document_intelligence.*</code> completion or failure events.</p>\n<h2 style=\"position:relative;\"><a href=\"#configure-a-webhook\" aria-label=\"configure a webhook permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"configure-a-webhook\"></div>Configure a webhook</h2>\n<p>Use Shipwell's webhook configuration API to subscribe an HTTPS endpoint to the document events your application needs.</p>\n<p>See <a href=\"/docs/webhook/use-webhook/\">Use Webhooks</a> for:</p>\n<ul>\n<li>\nCreating a webhook configuration\n</li>\n<li>\nVerifying Shipwell webhook signatures\n</li>\n<li>\nDelivery retries and timeouts\n</li>\n<li>\nDebugging unsuccessful deliveries\n</li>\n</ul>\n<!-- SCREENSHOT PLACEHOLDER\nFile: images/document-webhook-configuration.png\nCapture: Webhook configuration with the three document event types selected. Use a public-safe example URL.\nAlt: Webhook configuration for document lifecycle events\n-->\n<h2 style=\"position:relative;\"><a href=\"#event-payload\" aria-label=\"event payload permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"event-payload\"></div>Event payload</h2>\n<p>Webhook deliveries use the standard Shipwell event envelope. The <code class=\"language-text\">details</code> object contains the document-specific data.</p>\n<div class=\"code-wrapper\">\n        <div class=\"gatsby-code-button-container\"\n             data-toaster-id=\"57854011897236140000\"\n             data-toaster-duration=\"1500\"\n             onClick=\"copyCodeToClipboard(`{\n  &quot;id&quot;: &quot;<event-id>&quot;,\n  &quot;occurred_at&quot;: &quot;2026-07-15T12:00:00Z&quot;,\n  &quot;source&quot;: {\n    &quot;user_id&quot;: &quot;<user-id>&quot;,\n    &quot;company_id&quot;: &quot;<company-id>&quot;,\n    &quot;request_id&quot;: &quot;<request-id>&quot;,\n    &quot;publishing_system&quot;: &quot;document-store&quot;,\n    &quot;environment&quot;: &quot;sandbox&quot;\n  },\n  &quot;event_name&quot;: &quot;document.updated.v1&quot;,\n  &quot;details&quot;: {\n    &quot;id&quot;: &quot;<document-id>&quot;,\n    &quot;resource_type&quot;: &quot;document&quot;,\n    &quot;self_link&quot;: &quot;/document-store/documents/<document-id>/&quot;,\n    &quot;status&quot;: &quot;completed&quot;,\n    &quot;type&quot;: &quot;bill_of_lading&quot;,\n    &quot;filename&quot;: &quot;bol.pdf&quot;,\n    &quot;description&quot;: &quot;Bill of lading for a completed shipment.&quot;,\n    &quot;content_type&quot;: &quot;application/pdf&quot;,\n    &quot;size_bytes&quot;: 1832102,\n    &quot;associations&quot;: [\n      {&quot;entity_type&quot;: &quot;shipment&quot;, &quot;entity_id&quot;: &quot;SW-1001&quot;}\n    ],\n    &quot;old_data&quot;: {&quot;status&quot;: &quot;processing&quot;},\n    &quot;new_data&quot;: {&quot;status&quot;: &quot;completed&quot;},\n    &quot;run_id&quot;: &quot;<run-id>&quot;,\n    &quot;result_count&quot;: 1,\n    &quot;url&quot;: &quot;<temporary-download-url>&quot;,\n    &quot;url_expires_at&quot;: &quot;2026-07-15T12:15:00Z&quot;\n  }\n}`, `57854011897236140000`)\"\n        >\n          <div class=\"gatsby-code-button\" title=\"Copy the code snippet\">Copy</div>\n          <div class=\"done-indicator done-indicator-57854011897236140000\">Copied</div>\n        </div>\n        <div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;event-id>\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"occurred_at\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"2026-07-15T12:00:00Z\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"source\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"user_id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;user-id>\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"company_id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;company-id>\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"request_id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;request-id>\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"publishing_system\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"document-store\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"environment\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"sandbox\"</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"event_name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"document.updated.v1\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"details\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;document-id>\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"resource_type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"document\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"self_link\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/document-store/documents/&lt;document-id>/\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"status\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"completed\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bill_of_lading\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"filename\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bol.pdf\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Bill of lading for a completed shipment.\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"content_type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"application/pdf\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"size_bytes\"</span><span class=\"token operator\">:</span> <span class=\"token number\">1832102</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"associations\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token punctuation\">{</span><span class=\"token property\">\"entity_type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"shipment\"</span><span class=\"token punctuation\">,</span> <span class=\"token property\">\"entity_id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"SW-1001\"</span><span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"old_data\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token property\">\"status\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"processing\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"new_data\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token property\">\"status\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"completed\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"run_id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;run-id>\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"result_count\"</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"url\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"&lt;temporary-download-url>\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"url_expires_at\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"2026-07-15T12:15:00Z\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n      </div>\n<p>Fields can be absent when they do not apply. For example, <code class=\"language-text\">run_id</code> and <code class=\"language-text\">result_count</code> are associated with processing updates, while <code class=\"language-text\">delete_kind</code> can appear on a delete event.</p>\n<p>Treat <code class=\"language-text\">details.url</code> as a temporary, sensitive convenience URL. Store <code class=\"language-text\">details.id</code> and request a new download URL when needed.</p>\n<h2 style=\"position:relative;\"><a href=\"#event-behavior\" aria-label=\"event behavior permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"event-behavior\"></div>Event behavior</h2>\n<h3 style=\"position:relative;\"><a href=\"#documentcreatedv1\" aria-label=\"documentcreatedv1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"documentcreatedv1\"></div><code class=\"language-text\">document.created.v1</code></h3>\n<p>Sent after a document is created.</p>\n<p>The initial status can be:</p>\n<ul>\n<li>\n<code class=\"language-text\">pending</code>\n when processing was requested\n</li>\n<li>\nA stored, non-processing status when no configuration was selected\n</li>\n<li>\n<code class=\"language-text\">skipped</code>\n or \n<code class=\"language-text\">oversized</code>\n when the document was stored but was not eligible for processing\n</li>\n</ul>\n<p>AI-generated fields may not be available yet because processing is asynchronous.</p>\n<h3 style=\"position:relative;\"><a href=\"#documentupdatedv1\" aria-label=\"documentupdatedv1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"documentupdatedv1\"></div><code class=\"language-text\">document.updated.v1</code></h3>\n<p>Sent when document data or processing state changes. Processing outcomes are represented through <code class=\"language-text\">details.status</code>, commonly:</p>\n<ul>\n<li>\n<code class=\"language-text\">completed</code>\n</li>\n<li>\n<code class=\"language-text\">failed</code>\n</li>\n<li>\n<code class=\"language-text\">skipped</code>\n</li>\n<li>\n<code class=\"language-text\">oversized</code>\n</li>\n</ul>\n<p>Use <code class=\"language-text\">old_data</code> and <code class=\"language-text\">new_data</code> when you need to understand the changed fields. On a completed processing update, use <code class=\"language-text\">run_id</code> to retrieve the run and its results.</p>\n<h3 style=\"position:relative;\"><a href=\"#documentdeletedv1\" aria-label=\"documentdeletedv1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"documentdeletedv1\"></div><code class=\"language-text\">document.deleted.v1</code></h3>\n<p>Sent after document deletion. The payload identifies the deleted document and can include <code class=\"language-text\">delete_kind</code>.</p>\n<p>Do not attempt to use a temporary download URL from a delete event.</p>\n<h2 style=\"position:relative;\"><a href=\"#recommended-handler\" aria-label=\"recommended handler permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"recommended-handler\"></div>Recommended handler</h2>\n<ol>\n<li>\nVerify the webhook signature using the raw request body.\n</li>\n<li>\nPersist the delivery and return a \n<code class=\"language-text\">2xx</code>\n response promptly.\n</li>\n<li>\nProcess the event asynchronously.\n</li>\n<li>\nUpsert state by \n<code class=\"language-text\">details.id</code>\n.\n</li>\n<li>\nRetrieve the current document or run before performing downstream work.\n</li>\n</ol>\n<p>Example routing logic:</p>\n<div class=\"code-wrapper\">\n        <div class=\"gatsby-code-button-container\"\n             data-toaster-id=\"90800552646966070000\"\n             data-toaster-duration=\"1500\"\n             onClick=\"copyCodeToClipboard(`def handle_document_event(event):\n    event_name = event[&quot;event_name&quot;]\n    details = event[&quot;details&quot;]\n\n    if event_name == &quot;document.updated.v1&quot; and details.get(&quot;status&quot;) == &quot;completed&quot;:\n        enqueue_result_sync(\n            document_id=details[&quot;id&quot;],\n            run_id=details.get(&quot;run_id&quot;),\n        )\n    elif event_name == &quot;document.deleted.v1&quot;:\n        enqueue_document_removal(document_id=details[&quot;id&quot;])`, `90800552646966070000`)\"\n        >\n          <div class=\"gatsby-code-button\" title=\"Copy the code snippet\">Copy</div>\n          <div class=\"done-indicator done-indicator-90800552646966070000\">Copied</div>\n        </div>\n        <div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">def</span> <span class=\"token function\">handle_document_event</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    event_name <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"event_name\"</span><span class=\"token punctuation\">]</span>\n    details <span class=\"token operator\">=</span> event<span class=\"token punctuation\">[</span><span class=\"token string\">\"details\"</span><span class=\"token punctuation\">]</span>\n\n    <span class=\"token keyword\">if</span> event_name <span class=\"token operator\">==</span> <span class=\"token string\">\"document.updated.v1\"</span> <span class=\"token keyword\">and</span> details<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">\"status\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"completed\"</span><span class=\"token punctuation\">:</span>\n        enqueue_result_sync<span class=\"token punctuation\">(</span>\n            document_id<span class=\"token operator\">=</span>details<span class=\"token punctuation\">[</span><span class=\"token string\">\"id\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            run_id<span class=\"token operator\">=</span>details<span class=\"token punctuation\">.</span>get<span class=\"token punctuation\">(</span><span class=\"token string\">\"run_id\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">elif</span> event_name <span class=\"token operator\">==</span> <span class=\"token string\">\"document.deleted.v1\"</span><span class=\"token punctuation\">:</span>\n        enqueue_document_removal<span class=\"token punctuation\">(</span>document_id<span class=\"token operator\">=</span>details<span class=\"token punctuation\">[</span><span class=\"token string\">\"id\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></code></pre></div>\n      </div>\n<h2 style=\"position:relative;\"><a href=\"#delivery-safety\" aria-label=\"delivery safety permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><div class=\"hidden-anchor\" id=\"delivery-safety\"></div>Delivery safety</h2>\n<p>Webhook delivery is at least once, and events can arrive out of order.</p>\n<ul>\n<li>\nMake handlers idempotent.\n</li>\n<li>\nDo not assume the event identifier is sufficient to prevent every repeated business action.\n</li>\n<li>\nCompare \n<code class=\"language-text\">occurred_at</code>\n and retrieve current resource state before applying changes.\n</li>\n<li>\nAvoid depending on a strict \n<code class=\"language-text\">created</code>\n → \n<code class=\"language-text\">updated</code>\n → \n<code class=\"language-text\">deleted</code>\n arrival order.\n</li>\n<li>\nKeep side effects behind your own idempotency key.\n</li>\n</ul>","headings":[{"value":"Document Events and Webhooks","depth":1},{"value":"Configure a webhook","depth":2},{"value":"Event payload","depth":2},{"value":"Event behavior","depth":2},{"value":"<code class=\"language-text\">document.created.v1</code>","depth":3},{"value":"<code class=\"language-text\">document.updated.v1</code>","depth":3},{"value":"<code class=\"language-text\">document.deleted.v1</code>","depth":3},{"value":"Recommended handler","depth":2},{"value":"Delivery safety","depth":2}]},"contentItem":{"data":{"lastModified":"2026-07-17T16:00:10.000Z","enableToc":null,"disableLastModified":null,"tocMaxDepth":null,"requestLogin":false}},"siteConfig":{"enableToc":true,"disableLastModified":false,"tocMaxDepth":4}},"pageContext":{"matchPath":"","id":"971f0aeb-0f53-5d6e-9100-40a88d688207__redocly content/docs/ai/document-ai/events-and-webhooks/","seo":{"title":"Events and Webhooks","description":null,"image":"","keywords":null,"jsonLd":null,"lang":null,"siteUrl":null},"pageId":"docs/ai/document-ai/events-and-webhooks.md","pageBaseUrl":"/docs/ai/document-ai/events-and-webhooks","type":"markdown","toc":{"enable":true,"maxDepth":4,"headings":[{"depth":1,"value":"Document Events and Webhooks","id":"document-events-and-webhooks"},{"depth":2,"value":"Configure a webhook","id":"configure-a-webhook"},{"depth":2,"value":"Event payload","id":"event-payload"},{"depth":2,"value":"Event behavior","id":"event-behavior"},{"depth":3,"value":"<code class=\"language-text\">document.created.v1</code>","id":"documentcreatedv1"},{"depth":3,"value":"<code class=\"language-text\">document.updated.v1</code>","id":"documentupdatedv1"},{"depth":3,"value":"<code class=\"language-text\">document.deleted.v1</code>","id":"documentdeletedv1"},{"depth":2,"value":"Recommended handler","id":"recommended-handler"},{"depth":2,"value":"Delivery safety","id":"delivery-safety"}]},"data":{"title":"Events and Webhooks"},"catalogInfo":null,"link":"/docs/ai/document-ai/events-and-webhooks/","sidebarName":"developerPortal","isLanding":false,"showPrevButton":null,"showNextButton":null,"apiVersions":null,"apiVersionId":null,"isDefaultApiVersion":null}},"staticQueryHashes":["1123603147","1302185487","1344209882","1398840060","1520077861","1975142765","2667623876","2950305614","3240152602","3743992808","561138138"]}