[{"data":1,"prerenderedAt":3120},["ShallowReactive",2],{"blog-accounting-webhooks-integration-guide":3},{"post":4,"related":3119},{"id":5,"title":6,"author":7,"body":8,"category":3082,"cluster":3083,"contributors":3084,"coverImage":3085,"createdAt":3089,"cta":3090,"description":14,"extension":3096,"featured":3097,"meta":3098,"navigation":1246,"path":3099,"publishedAt":3089,"readingMinutes":3100,"seo":3101,"slug":3104,"status":3105,"stem":3106,"subtitle":3107,"tags":3108,"updatedAt":3117,"__hash__":3118},"blog\u002Fblog\u002F2026\u002F08\u002F22-accounting-webhooks.md","Accounting Webhooks Integration Guide","newledger-team",{"type":9,"value":10,"toc":3063},"minimark",[11,15,20,98,103,168,176,196,207,210,213,432,509,512,515,518,545,548,554,557,564,1007,1010,1014,1025,1034,1037,1049,1057,1115,1118,1146,1152,1156,1163,2584,2595,2599,2606,2612,2622,2684,2687,2704,2710,2713,2716,2722,2789,2801,2804,2850,2866,2879,2882,2885,2891,2894,2935,2938,2941,2944,2947,2963,2966,3051,3059],[12,13,14],"p",{},"NewLedger webhooks notify your integration when committed accounting data changes. Use them to start a workflow; use the company-scoped API when you need the authoritative resource.",[16,17,19],"h2",{"id":18},"quick-reference","Quick reference",[21,22,23,36],"table",{},[24,25,26],"thead",{},[27,28,29,33],"tr",{},[30,31,32],"th",{},"Contract",[30,34,35],{},"Value",[37,38,39,53,61,69,80,88],"tbody",{},[27,40,41,45],{},[42,43,44],"td",{},"Acknowledge",[42,46,47,48,52],{},"Any ",[49,50,51],"code",{},"2xx"," response",[27,54,55,58],{},[42,56,57],{},"Signature",[42,59,60],{},"HMAC-SHA256",[27,62,63,66],{},[42,64,65],{},"Timestamp tolerance",[42,67,68],{},"Five minutes",[27,70,71,74],{},[42,72,73],{},"Dedupe key",[42,75,76,77],{},"Event ",[49,78,79],{},"id",[27,81,82,85],{},[42,83,84],{},"Delivery timeout",[42,86,87],{},"15 seconds",[27,89,90,93],{},[42,91,92],{},"Retry schedule",[42,94,95],{},[49,96,97],{},"1m → 10m → 1h → 8h → 24h → 48h",[99,100,102],"h3",{"id":101},"on-this-page","On this page",[104,105,106,114,120,126,132,138,144,150,156,162],"ul",{},[107,108,109],"li",{},[110,111,113],"a",{"href":112},"#event-envelope","Event envelope",[107,115,116],{},[110,117,119],{"href":118},"#receiver-flow","Receiver flow",[107,121,122],{},[110,123,125],{"href":124},"#event-catalog","Event catalog",[107,127,128],{},[110,129,131],{"href":130},"#signing-and-verification","Signing and verification",[107,133,134],{},[110,135,137],{"href":136},"#rotate-a-signing-secret-without-interrupting-delivery","Secret rotation",[107,139,140],{},[110,141,143],{"href":142},"#delivery-retries","Delivery retries",[107,145,146],{},[110,147,149],{"href":148},"#timeouts-and-redirects","Timeouts and redirects",[107,151,152],{},[110,153,155],{"href":154},"#idempotent-processing","Idempotent processing",[107,157,158],{},[110,159,161],{"href":160},"#endpoint-health-and-recovery","Endpoint health and recovery",[107,163,164],{},[110,165,167],{"href":166},"#production-checklist","Production checklist",[12,169,170,171,175],{},"The delivery contract is ",[172,173,174],"strong",{},"asynchronous and at least once",":",[104,177,178,181,184,187,193],{},[107,179,180],{},"events can be delivered more than once",[107,182,183],{},"related events can arrive out of order",[107,185,186],{},"unavailable endpoints are retried",[107,188,189,190,192],{},"any ",[49,191,51],{}," response acknowledges the delivery",[107,194,195],{},"consumers must deduplicate before applying business effects",[197,198,201],"webhook-callout",{"title":199,"tone":200},"Design for duplicate delivery","warning",[12,202,203,204,206],{},"Persist the event ",[49,205,79],{}," before applying a payment, journal, entitlement, or notification. A successful HTTP response without durable deduplication can repeat the business effect.",[16,208,113],{"id":209},"event-envelope",[12,211,212],{},"NewLedger sends a thin notification rather than a full resource snapshot:",[214,215,220],"pre",{"className":216,"code":217,"language":218,"meta":219,"style":219},"language-json shiki shiki-themes material-theme-lighter github-light github-dark","{\n  \"id\": \"evt_0191a2b3-c4d5-7000-8000-000000000001\",\n  \"type\": \"sales.invoice.updated\",\n  \"version\": \"1.0\",\n  \"company_id\": \"0191a2b3-c4d5-7000-8000-000000000010\",\n  \"actor_id\": \"0191a2b3-c4d5-7000-8000-000000000030\",\n  \"occurred_at\": \"2026-08-18T08:15:00.123Z\",\n  \"resource\": {\n    \"id\": \"0191a2b3-c4d5-7000-8000-000000000020\",\n    \"type\": \"invoice\"\n  }\n}\n","json","",[49,221,222,231,259,280,301,322,343,364,379,401,420,426],{"__ignoreMap":219},[223,224,227],"span",{"class":225,"line":226},"line",1,[223,228,230],{"class":229},"sP7_E","{\n",[223,232,234,238,241,244,246,250,254,256],{"class":225,"line":233},2,[223,235,237],{"class":236},"s39Yj","  \"",[223,239,79],{"class":240},"sseR_",[223,242,243],{"class":236},"\"",[223,245,175],{"class":229},[223,247,249],{"class":248},"sjJ54"," \"",[223,251,253],{"class":252},"s_sjI","evt_0191a2b3-c4d5-7000-8000-000000000001",[223,255,243],{"class":248},[223,257,258],{"class":229},",\n",[223,260,262,264,267,269,271,273,276,278],{"class":225,"line":261},3,[223,263,237],{"class":236},[223,265,266],{"class":240},"type",[223,268,243],{"class":236},[223,270,175],{"class":229},[223,272,249],{"class":248},[223,274,275],{"class":252},"sales.invoice.updated",[223,277,243],{"class":248},[223,279,258],{"class":229},[223,281,283,285,288,290,292,294,297,299],{"class":225,"line":282},4,[223,284,237],{"class":236},[223,286,287],{"class":240},"version",[223,289,243],{"class":236},[223,291,175],{"class":229},[223,293,249],{"class":248},[223,295,296],{"class":252},"1.0",[223,298,243],{"class":248},[223,300,258],{"class":229},[223,302,304,306,309,311,313,315,318,320],{"class":225,"line":303},5,[223,305,237],{"class":236},[223,307,308],{"class":240},"company_id",[223,310,243],{"class":236},[223,312,175],{"class":229},[223,314,249],{"class":248},[223,316,317],{"class":252},"0191a2b3-c4d5-7000-8000-000000000010",[223,319,243],{"class":248},[223,321,258],{"class":229},[223,323,325,327,330,332,334,336,339,341],{"class":225,"line":324},6,[223,326,237],{"class":236},[223,328,329],{"class":240},"actor_id",[223,331,243],{"class":236},[223,333,175],{"class":229},[223,335,249],{"class":248},[223,337,338],{"class":252},"0191a2b3-c4d5-7000-8000-000000000030",[223,340,243],{"class":248},[223,342,258],{"class":229},[223,344,346,348,351,353,355,357,360,362],{"class":225,"line":345},7,[223,347,237],{"class":236},[223,349,350],{"class":240},"occurred_at",[223,352,243],{"class":236},[223,354,175],{"class":229},[223,356,249],{"class":248},[223,358,359],{"class":252},"2026-08-18T08:15:00.123Z",[223,361,243],{"class":248},[223,363,258],{"class":229},[223,365,367,369,372,374,376],{"class":225,"line":366},8,[223,368,237],{"class":236},[223,370,371],{"class":240},"resource",[223,373,243],{"class":236},[223,375,175],{"class":229},[223,377,378],{"class":229}," {\n",[223,380,382,385,388,390,392,394,397,399],{"class":225,"line":381},9,[223,383,384],{"class":236},"    \"",[223,386,79],{"class":387},"sZMiF",[223,389,243],{"class":236},[223,391,175],{"class":229},[223,393,249],{"class":248},[223,395,396],{"class":252},"0191a2b3-c4d5-7000-8000-000000000020",[223,398,243],{"class":248},[223,400,258],{"class":229},[223,402,404,406,408,410,412,414,417],{"class":225,"line":403},10,[223,405,384],{"class":236},[223,407,266],{"class":387},[223,409,243],{"class":236},[223,411,175],{"class":229},[223,413,249],{"class":248},[223,415,416],{"class":252},"invoice",[223,418,419],{"class":248},"\"\n",[223,421,423],{"class":225,"line":422},11,[223,424,425],{"class":229},"  }\n",[223,427,429],{"class":225,"line":428},12,[223,430,431],{"class":229},"}\n",[21,433,434,444],{},[24,435,436],{},[27,437,438,441],{},[30,439,440],{},"Field",[30,442,443],{},"Purpose",[37,445,446,455,464,473,482,491,500],{},[27,447,448,452],{},[42,449,450],{},[49,451,79],{},[42,453,454],{},"Immutable event identity; use this for deduplication",[27,456,457,461],{},[42,458,459],{},[49,460,266],{},[42,462,463],{},"Stable accounting event name",[27,465,466,470],{},[42,467,468],{},[49,469,287],{},[42,471,472],{},"Envelope contract version",[27,474,475,479],{},[42,476,477],{},[49,478,308],{},[42,480,481],{},"Company that owns the resource",[27,483,484,488],{},[42,485,486],{},[49,487,329],{},[42,489,490],{},"Initiating actor when known",[27,492,493,497],{},[42,494,495],{},[49,496,350],{},[42,498,499],{},"Time the accounting change committed",[27,501,502,506],{},[42,503,504],{},[49,505,371],{},[42,507,508],{},"Public resource type and ID to retrieve through the API",[12,510,511],{},"The notification is immutable. The referenced resource can change again before your integration retrieves it.",[16,513,119],{"id":514},"receiver-flow",[12,516,517],{},"Your endpoint receives and verifies the signed notification, persists its event ID for deduplication, and acknowledges it. Processing then follows one of two paths:",[104,519,520,531],{},[107,521,522,525,526,530],{},[172,523,524],{},"Hydratable resource:"," retrieve the latest state when the ",[110,527,529],{"href":528},"\u002Fapi-documentation","NewLedger API documentation"," provides a corresponding read operation.",[107,532,533,536,537,540,541,544],{},[172,534,535],{},"Notification-only event:"," use the verified event as a signal. Payment and credit-note application events identify a ",[49,538,539],{},"document_payment",", not its parent document, and cannot be hydrated by ID in v1. Also subscribe to the corresponding ",[49,542,543],{},"*.status.changed"," event when you need document state, or reconcile through the relevant list API.",[546,547],"webhook-flow-diagram",{},[12,549,550,551,553],{},"Return ",[49,552,51],{}," after durably accepting a valid notification. Hydration and business processing should run asynchronously. Use the immutable event ID to ensure a repeated delivery does not repeat the same business effect.",[16,555,125],{"id":556},"event-catalog",[12,558,559,560,563],{},"Event names follow ",[49,561,562],{},"\u003Cdomain>.\u003Cresource>[.\u003Csubresource>].\u003Caction>",". Subscriptions contain explicit event names, so future catalog additions do not silently expand an existing endpoint's access.",[21,565,566,576],{},[24,567,568],{},[27,569,570,573],{},[30,571,572],{},"Group",[30,574,575],{},"Events",[37,577,578,611,643,665,687,718,750,782,809,831,863,895,912,934,956,968,985],{},[27,579,580,585],{},[42,581,582],{},[172,583,584],{},"Accounting · Account",[42,586,587,590,593,596,598,601,603,606,608],{},[49,588,589],{},"accounting.account.created",[591,592],"br",{},[49,594,595],{},"accounting.account.updated",[591,597],{},[49,599,600],{},"accounting.account.archived",[591,602],{},[49,604,605],{},"accounting.account.restored",[591,607],{},[49,609,610],{},"accounting.account.deleted",[27,612,613,618],{},[42,614,615],{},[172,616,617],{},"Accounting · Journal",[42,619,620,623,625,628,630,633,635,638,640],{},[49,621,622],{},"accounting.journal.created",[591,624],{},[49,626,627],{},"accounting.journal.updated",[591,629],{},[49,631,632],{},"accounting.journal.posted",[591,634],{},[49,636,637],{},"accounting.journal.voided",[591,639],{},[49,641,642],{},"accounting.journal.deleted",[27,644,645,650],{},[42,646,647],{},[172,648,649],{},"Contacts · Client",[42,651,652,655,657,660,662],{},[49,653,654],{},"contacts.client.created",[591,656],{},[49,658,659],{},"contacts.client.updated",[591,661],{},[49,663,664],{},"contacts.client.deleted",[27,666,667,672],{},[42,668,669],{},[172,670,671],{},"Contacts · Vendor",[42,673,674,677,679,682,684],{},[49,675,676],{},"contacts.vendor.created",[591,678],{},[49,680,681],{},"contacts.vendor.updated",[591,683],{},[49,685,686],{},"contacts.vendor.deleted",[27,688,689,694],{},[42,690,691],{},[172,692,693],{},"Sales · Invoice",[42,695,696,699,701,703,705,708,710,713,715],{},[49,697,698],{},"sales.invoice.created",[591,700],{},[49,702,275],{},[591,704],{},[49,706,707],{},"sales.invoice.status.changed",[591,709],{},[49,711,712],{},"sales.invoice.payment.recorded",[591,714],{},[49,716,717],{},"sales.invoice.payment.reversed",[27,719,720,725],{},[42,721,722],{},[172,723,724],{},"Purchases · Bill",[42,726,727,730,732,735,737,740,742,745,747],{},[49,728,729],{},"purchases.bill.created",[591,731],{},[49,733,734],{},"purchases.bill.updated",[591,736],{},[49,738,739],{},"purchases.bill.status.changed",[591,741],{},[49,743,744],{},"purchases.bill.payment.recorded",[591,746],{},[49,748,749],{},"purchases.bill.payment.reversed",[27,751,752,757],{},[42,753,754],{},[172,755,756],{},"Sales · Credit note",[42,758,759,762,764,767,769,772,774,777,779],{},[49,760,761],{},"sales.credit_note.created",[591,763],{},[49,765,766],{},"sales.credit_note.updated",[591,768],{},[49,770,771],{},"sales.credit_note.status.changed",[591,773],{},[49,775,776],{},"sales.credit_note.applied",[591,778],{},[49,780,781],{},"sales.credit_note.application_reversed",[27,783,784,789],{},[42,785,786],{},[172,787,788],{},"Expenses · Expense",[42,790,791,794,796,799,801,804,806],{},[49,792,793],{},"expenses.expense.created",[591,795],{},[49,797,798],{},"expenses.expense.updated",[591,800],{},[49,802,803],{},"expenses.expense.deleted",[591,805],{},[49,807,808],{},"expenses.expense.status.changed",[27,810,811,816],{},[42,812,813],{},[172,814,815],{},"Items · Item",[42,817,818,821,823,826,828],{},[49,819,820],{},"items.item.created",[591,822],{},[49,824,825],{},"items.item.updated",[591,827],{},[49,829,830],{},"items.item.deleted",[27,832,833,838],{},[42,834,835],{},[172,836,837],{},"Company · Profile",[42,839,840,843,845,848,850,853,855,858,860],{},[49,841,842],{},"company.profile.updated",[591,844],{},[49,846,847],{},"company.profile.deleted",[591,849],{},[49,851,852],{},"company.status.changed",[591,854],{},[49,856,857],{},"company.logo.updated",[591,859],{},[49,861,862],{},"company.logo.deleted",[27,864,865,870],{},[42,866,867],{},[172,868,869],{},"Company · User",[42,871,872,875,877,880,882,885,887,890,892],{},[49,873,874],{},"company.user.created",[591,876],{},[49,878,879],{},"company.user.updated",[591,881],{},[49,883,884],{},"company.user.status.changed",[591,886],{},[49,888,889],{},"company.user.role.changed",[591,891],{},[49,893,894],{},"company.user.deleted",[27,896,897,902],{},[42,898,899],{},[172,900,901],{},"Settings · Currency",[42,903,904,907,909],{},[49,905,906],{},"settings.currency.created",[591,908],{},[49,910,911],{},"settings.currency.deleted",[27,913,914,919],{},[42,915,916],{},[172,917,918],{},"Settings · Payment term",[42,920,921,924,926,929,931],{},[49,922,923],{},"settings.payment_term.created",[591,925],{},[49,927,928],{},"settings.payment_term.updated",[591,930],{},[49,932,933],{},"settings.payment_term.deleted",[27,935,936,941],{},[42,937,938],{},[172,939,940],{},"Settings · Payment mode",[42,942,943,946,948,951,953],{},[49,944,945],{},"settings.payment_mode.created",[591,947],{},[49,949,950],{},"settings.payment_mode.updated",[591,952],{},[49,954,955],{},"settings.payment_mode.deleted",[27,957,958,963],{},[42,959,960],{},[172,961,962],{},"Settings · Email template",[42,964,965],{},[49,966,967],{},"settings.email_template.updated",[27,969,970,975],{},[42,971,972],{},[172,973,974],{},"Settings · SMTP",[42,976,977,980,982],{},[49,978,979],{},"settings.smtp.updated",[591,981],{},[49,983,984],{},"settings.smtp.deleted",[27,986,987,992],{},[42,988,989],{},[172,990,991],{},"Settings · Payment gateway",[42,993,994,997,999,1002,1004],{},[49,995,996],{},"settings.payment_gateway.created",[591,998],{},[49,1000,1001],{},"settings.payment_gateway.updated",[591,1003],{},[49,1005,1006],{},"settings.payment_gateway.deleted",[12,1008,1009],{},"An invoice change and its accounting journal posting are separate commits. Subscribe to the business transitions you use rather than infer one event from another.",[99,1011,1013],{"id":1012},"endpoint-verification-event","Endpoint verification event",[12,1015,1016,1017,1020,1021,1024],{},"The 62 names above are subscribable business events. Endpoint activation also sends a required, non-catalog event with ",[49,1018,1019],{},"type: \"webhook.endpoint.verification\""," and ",[49,1022,1023],{},"resource.type: \"webhook_endpoint\"",".",[12,1026,1027,1028,1030,1031,1024],{},"Verify it with the same raw-body HMAC headers and return ",[49,1029,51],{},". Do not reject it with a business-event allowlist, and do not run a business workflow for it. Otherwise the endpoint remains in ",[49,1032,1033],{},"pending_verification",[16,1035,131],{"id":1036},"signing-and-verification",[12,1038,1039,1040,1044,1045,1048],{},"Each endpoint has its own signing secret, separate from App Connect authentication. Review ",[110,1041,1043],{"href":1042},"\u002Fblog\u002Fapi-credentials-vs-oauth-2-0","API credentials versus OAuth 2.0"," when choosing how the receiver will authenticate its follow-up API request. NewLedger signs the timestamp plus the ",[172,1046,1047],{},"exact raw request body"," with HMAC-SHA256.",[214,1050,1055],{"className":1051,"code":1053,"language":1054,"meta":219},[1052],"language-text","signed_payload = timestamp + \".\" + raw_body\nsignature      = HMAC-SHA256(endpoint_secret, signed_payload)\n","text",[49,1056,1053],{"__ignoreMap":219},[21,1058,1059,1068],{},[24,1060,1061],{},[27,1062,1063,1066],{},[30,1064,1065],{},"Header",[30,1067,35],{},[37,1069,1070,1082,1092,1102],{},[27,1071,1072,1077],{},[42,1073,1074],{},[49,1075,1076],{},"Webhook-Signature",[42,1078,1079],{},[49,1080,1081],{},"t=\u003Cunix-seconds>;v1=\u003Clowercase-hex>",[27,1083,1084,1089],{},[42,1085,1086],{},[49,1087,1088],{},"Webhook-Event-Id",[42,1090,1091],{},"Immutable event ID",[27,1093,1094,1099],{},[42,1095,1096],{},[49,1097,1098],{},"Webhook-Delivery-Attempt",[42,1100,1101],{},"Attempt number",[27,1103,1104,1109],{},[42,1105,1106],{},[49,1107,1108],{},"User-Agent",[42,1110,1111,1112],{},"Partner identity, for example ",[49,1113,1114],{},"NewLedger-Webhooks\u002F1.0",[12,1116,1117],{},"Verify requests in this order:",[1119,1120,1121,1124,1131,1134,1140,1143],"ol",{},[107,1122,1123],{},"Capture the body before JSON middleware transforms it.",[107,1125,1126,1127,1130],{},"Parse the timestamp and one or more ",[49,1128,1129],{},"v1"," signatures.",[107,1132,1133],{},"Reject a timestamp outside the five-minute tolerance.",[107,1135,1136,1137,1024],{},"Calculate HMAC-SHA256 over ",[49,1138,1139],{},"timestamp + \".\" + raw_body",[107,1141,1142],{},"Compare the expected and supplied values in constant time.",[107,1144,1145],{},"Parse the event and store its ID only after verification succeeds.",[197,1147,1149],{"title":1148,"tone":200},"Verify the bytes you received",[12,1150,1151],{},"Parsing and serializing JSON can change whitespace or field order. Calculate the signature from the untouched request body, not reconstructed JSON.",[99,1153,1155],{"id":1154},"complete-nodejs-and-typescript-receiver","Complete Node.js and TypeScript receiver",[12,1157,1158,1159,1162],{},"This Express example preserves the raw bytes, accepts either trusted secret during rotation, compares signatures in constant time, durably accepts the event, and returns before hydration or business processing. Configure ",[49,1160,1161],{},"express.raw"," before any JSON parser for this route.",[214,1164,1168],{"className":1165,"code":1166,"language":1167,"meta":219,"style":219},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import express, { type Request, type Response } from \"express\";\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\n\nconst app = express();\nconst trustedSecrets = [\n  process.env.WEBHOOK_SECRET_CURRENT,\n  process.env.WEBHOOK_SECRET_PREVIOUS,\n].filter((secret): secret is string => Boolean(secret));\n\nfunction verifyWebhook(rawBody: Buffer, header: string): boolean {\n  const parts = header.split(\";\").map((part) => part.trim());\n  const timestamp = parts.find((part) => part.startsWith(\"t=\"))?.slice(2);\n  const supplied = parts\n    .filter((part) => part.startsWith(\"v1=\"))\n    .map((part) => part.slice(3));\n\n  if (!timestamp || !\u002F^\\d+$\u002F.test(timestamp) || supplied.length === 0) return false;\n  if (Math.abs(Math.floor(Date.now() \u002F 1000) - Number(timestamp)) > 300) return false;\n\n  const signedPayload = Buffer.concat([\n    Buffer.from(`${timestamp}.`, \"utf8\"),\n    rawBody,\n  ]);\n\n  return trustedSecrets.some((secret) => {\n    const expected = createHmac(\"sha256\", secret)\n      .update(signedPayload)\n      .digest();\n\n    return supplied.some((hex) => {\n      if (!\u002F^[0-9a-f]{64}$\u002Fi.test(hex)) return false;\n      const actual = Buffer.from(hex, \"hex\");\n      return actual.length === expected.length && timingSafeEqual(actual, expected);\n    });\n  });\n}\n\ntype WebhookEvent = { id: string; type: string };\n\nasync function persistForProcessing(event: WebhookEvent): Promise\u003Cvoid> {\n  \u002F\u002F Insert event.id with a unique constraint and enqueue the event atomically.\n  \u002F\u002F A worker—not this request—hydrates available resources and runs workflows.\n  console.log(event);\n}\n\napp.post(\n  \"\u002Fwebhooks\u002Fnewledger\",\n  express.raw({ type: \"application\u002Fjson\" }),\n  async (req: Request, res: Response) => {\n    const signature = req.get(\"Webhook-Signature\");\n    if (!signature || !verifyWebhook(req.body, signature)) {\n      return res.status(401).send(\"Invalid signature\");\n    }\n\n    const event = JSON.parse(req.body.toString(\"utf8\")) as WebhookEvent;\n\n    if (event.type === \"webhook.endpoint.verification\") {\n      return res.sendStatus(204);\n    }\n\n    \u002F\u002F Keep this durable handoff short; never hydrate or run business logic here.\n    await persistForProcessing(event);\n    return res.sendStatus(204);\n  },\n);\n","ts",[49,1169,1170,1215,1242,1248,1270,1282,1299,1314,1358,1362,1399,1457,1518,1531,1567,1599,1604,1682,1753,1758,1778,1817,1825,1833,1838,1863,1892,1908,1920,1925,1950,1999,2032,2070,2080,2090,2095,2100,2131,2136,2174,2181,2187,2206,2211,2216,2230,2242,2275,2305,2335,2372,2409,2415,2420,2468,2473,2499,2520,2525,2530,2536,2552,2571,2577],{"__ignoreMap":219},[223,1171,1172,1176,1180,1183,1186,1189,1192,1194,1196,1199,1202,1205,1207,1210,1212],{"class":225,"line":226},[223,1173,1175],{"class":1174},"sVHd0","import",[223,1177,1179],{"class":1178},"su5hD"," express",[223,1181,1182],{"class":229},",",[223,1184,1185],{"class":229}," {",[223,1187,1188],{"class":1174}," type",[223,1190,1191],{"class":1178}," Request",[223,1193,1182],{"class":229},[223,1195,1188],{"class":1174},[223,1197,1198],{"class":1178}," Response",[223,1200,1201],{"class":229}," }",[223,1203,1204],{"class":1174}," from",[223,1206,249],{"class":248},[223,1208,1209],{"class":252},"express",[223,1211,243],{"class":248},[223,1213,1214],{"class":229},";\n",[223,1216,1217,1219,1221,1224,1226,1229,1231,1233,1235,1238,1240],{"class":225,"line":233},[223,1218,1175],{"class":1174},[223,1220,1185],{"class":229},[223,1222,1223],{"class":1178}," createHmac",[223,1225,1182],{"class":229},[223,1227,1228],{"class":1178}," timingSafeEqual",[223,1230,1201],{"class":229},[223,1232,1204],{"class":1174},[223,1234,249],{"class":248},[223,1236,1237],{"class":252},"node:crypto",[223,1239,243],{"class":248},[223,1241,1214],{"class":229},[223,1243,1244],{"class":225,"line":261},[223,1245,1247],{"emptyLinePlaceholder":1246},true,"\n",[223,1249,1250,1254,1258,1262,1265,1268],{"class":225,"line":282},[223,1251,1253],{"class":1252},"sbsja","const",[223,1255,1257],{"class":1256},"s_hVV"," app",[223,1259,1261],{"class":1260},"smGrS"," =",[223,1263,1179],{"class":1264},"sGLFI",[223,1266,1267],{"class":1178},"()",[223,1269,1214],{"class":229},[223,1271,1272,1274,1277,1279],{"class":225,"line":303},[223,1273,1253],{"class":1252},[223,1275,1276],{"class":1256}," trustedSecrets",[223,1278,1261],{"class":1260},[223,1280,1281],{"class":1178}," [\n",[223,1283,1284,1287,1289,1292,1294,1297],{"class":225,"line":324},[223,1285,1286],{"class":1178},"  process",[223,1288,1024],{"class":229},[223,1290,1291],{"class":1178},"env",[223,1293,1024],{"class":229},[223,1295,1296],{"class":1256},"WEBHOOK_SECRET_CURRENT",[223,1298,258],{"class":229},[223,1300,1301,1303,1305,1307,1309,1312],{"class":225,"line":345},[223,1302,1286],{"class":1178},[223,1304,1024],{"class":229},[223,1306,1291],{"class":1178},[223,1308,1024],{"class":229},[223,1310,1311],{"class":1256},"WEBHOOK_SECRET_PREVIOUS",[223,1313,258],{"class":229},[223,1315,1316,1319,1321,1324,1327,1329,1333,1336,1338,1341,1344,1347,1350,1353,1356],{"class":225,"line":366},[223,1317,1318],{"class":1178},"]",[223,1320,1024],{"class":229},[223,1322,1323],{"class":1264},"filter",[223,1325,1326],{"class":1178},"(",[223,1328,1326],{"class":229},[223,1330,1332],{"class":1331},"s99_P","secret",[223,1334,1335],{"class":229},")",[223,1337,175],{"class":1260},[223,1339,1340],{"class":1331}," secret",[223,1342,1343],{"class":1260}," is",[223,1345,1346],{"class":387}," string",[223,1348,1349],{"class":1252}," =>",[223,1351,1352],{"class":1264}," Boolean",[223,1354,1355],{"class":1178},"(secret))",[223,1357,1214],{"class":229},[223,1359,1360],{"class":225,"line":381},[223,1361,1247],{"emptyLinePlaceholder":1246},[223,1363,1364,1367,1370,1372,1375,1377,1381,1383,1386,1388,1390,1392,1394,1397],{"class":225,"line":403},[223,1365,1366],{"class":1252},"function",[223,1368,1369],{"class":1264}," verifyWebhook",[223,1371,1326],{"class":229},[223,1373,1374],{"class":1331},"rawBody",[223,1376,175],{"class":1260},[223,1378,1380],{"class":1379},"sbgvK"," Buffer",[223,1382,1182],{"class":229},[223,1384,1385],{"class":1331}," header",[223,1387,175],{"class":1260},[223,1389,1346],{"class":387},[223,1391,1335],{"class":229},[223,1393,175],{"class":1260},[223,1395,1396],{"class":387}," boolean",[223,1398,378],{"class":229},[223,1400,1401,1404,1407,1409,1411,1413,1416,1419,1421,1424,1426,1428,1430,1433,1435,1437,1440,1442,1444,1447,1449,1452,1455],{"class":225,"line":422},[223,1402,1403],{"class":1252},"  const",[223,1405,1406],{"class":1256}," parts",[223,1408,1261],{"class":1260},[223,1410,1385],{"class":1178},[223,1412,1024],{"class":229},[223,1414,1415],{"class":1264},"split",[223,1417,1326],{"class":1418},"skxfh",[223,1420,243],{"class":248},[223,1422,1423],{"class":252},";",[223,1425,243],{"class":248},[223,1427,1335],{"class":1418},[223,1429,1024],{"class":229},[223,1431,1432],{"class":1264},"map",[223,1434,1326],{"class":1418},[223,1436,1326],{"class":229},[223,1438,1439],{"class":1331},"part",[223,1441,1335],{"class":229},[223,1443,1349],{"class":1252},[223,1445,1446],{"class":1178}," part",[223,1448,1024],{"class":229},[223,1450,1451],{"class":1264},"trim",[223,1453,1454],{"class":1418},"())",[223,1456,1214],{"class":229},[223,1458,1459,1461,1464,1466,1468,1470,1473,1475,1477,1479,1481,1483,1485,1487,1490,1492,1494,1497,1499,1502,1505,1508,1510,1514,1516],{"class":225,"line":428},[223,1460,1403],{"class":1252},[223,1462,1463],{"class":1256}," timestamp",[223,1465,1261],{"class":1260},[223,1467,1406],{"class":1178},[223,1469,1024],{"class":229},[223,1471,1472],{"class":1264},"find",[223,1474,1326],{"class":1418},[223,1476,1326],{"class":229},[223,1478,1439],{"class":1331},[223,1480,1335],{"class":229},[223,1482,1349],{"class":1252},[223,1484,1446],{"class":1178},[223,1486,1024],{"class":229},[223,1488,1489],{"class":1264},"startsWith",[223,1491,1326],{"class":1418},[223,1493,243],{"class":248},[223,1495,1496],{"class":252},"t=",[223,1498,243],{"class":248},[223,1500,1501],{"class":1418},"))",[223,1503,1504],{"class":229},"?.",[223,1506,1507],{"class":1264},"slice",[223,1509,1326],{"class":1418},[223,1511,1513],{"class":1512},"srdBf","2",[223,1515,1335],{"class":1418},[223,1517,1214],{"class":229},[223,1519,1521,1523,1526,1528],{"class":225,"line":1520},13,[223,1522,1403],{"class":1252},[223,1524,1525],{"class":1256}," supplied",[223,1527,1261],{"class":1260},[223,1529,1530],{"class":1178}," parts\n",[223,1532,1534,1537,1539,1541,1543,1545,1547,1549,1551,1553,1555,1557,1559,1562,1564],{"class":225,"line":1533},14,[223,1535,1536],{"class":229},"    .",[223,1538,1323],{"class":1264},[223,1540,1326],{"class":1418},[223,1542,1326],{"class":229},[223,1544,1439],{"class":1331},[223,1546,1335],{"class":229},[223,1548,1349],{"class":1252},[223,1550,1446],{"class":1178},[223,1552,1024],{"class":229},[223,1554,1489],{"class":1264},[223,1556,1326],{"class":1418},[223,1558,243],{"class":248},[223,1560,1561],{"class":252},"v1=",[223,1563,243],{"class":248},[223,1565,1566],{"class":1418},"))\n",[223,1568,1570,1572,1574,1576,1578,1580,1582,1584,1586,1588,1590,1592,1595,1597],{"class":225,"line":1569},15,[223,1571,1536],{"class":229},[223,1573,1432],{"class":1264},[223,1575,1326],{"class":1418},[223,1577,1326],{"class":229},[223,1579,1439],{"class":1331},[223,1581,1335],{"class":229},[223,1583,1349],{"class":1252},[223,1585,1446],{"class":1178},[223,1587,1024],{"class":229},[223,1589,1507],{"class":1264},[223,1591,1326],{"class":1418},[223,1593,1594],{"class":1512},"3",[223,1596,1501],{"class":1418},[223,1598,1214],{"class":229},[223,1600,1602],{"class":225,"line":1601},16,[223,1603,1247],{"emptyLinePlaceholder":1246},[223,1605,1607,1610,1613,1616,1619,1622,1625,1628,1631,1635,1638,1641,1643,1645,1648,1650,1652,1655,1658,1660,1662,1665,1668,1671,1673,1676,1680],{"class":225,"line":1606},17,[223,1608,1609],{"class":1174},"  if",[223,1611,1612],{"class":1418}," (",[223,1614,1615],{"class":1260},"!",[223,1617,1618],{"class":1178},"timestamp",[223,1620,1621],{"class":1260}," ||",[223,1623,1624],{"class":1260}," !",[223,1626,1627],{"class":248},"\u002F",[223,1629,1630],{"class":1174},"^",[223,1632,1634],{"class":1633},"stzsN","\\d",[223,1636,1637],{"class":1260},"+",[223,1639,1640],{"class":1174},"$",[223,1642,1627],{"class":248},[223,1644,1024],{"class":229},[223,1646,1647],{"class":1264},"test",[223,1649,1326],{"class":1418},[223,1651,1618],{"class":1178},[223,1653,1654],{"class":1418},") ",[223,1656,1657],{"class":1260},"||",[223,1659,1525],{"class":1178},[223,1661,1024],{"class":229},[223,1663,1664],{"class":1256},"length",[223,1666,1667],{"class":1260}," ===",[223,1669,1670],{"class":1512}," 0",[223,1672,1654],{"class":1418},[223,1674,1675],{"class":1174},"return",[223,1677,1679],{"class":1678},"syTEX"," false",[223,1681,1214],{"class":229},[223,1683,1685,1687,1689,1692,1694,1697,1699,1701,1703,1706,1708,1711,1713,1716,1719,1721,1724,1726,1729,1732,1734,1736,1739,1742,1745,1747,1749,1751],{"class":225,"line":1684},18,[223,1686,1609],{"class":1174},[223,1688,1612],{"class":1418},[223,1690,1691],{"class":1178},"Math",[223,1693,1024],{"class":229},[223,1695,1696],{"class":1264},"abs",[223,1698,1326],{"class":1418},[223,1700,1691],{"class":1178},[223,1702,1024],{"class":229},[223,1704,1705],{"class":1264},"floor",[223,1707,1326],{"class":1418},[223,1709,1710],{"class":1178},"Date",[223,1712,1024],{"class":229},[223,1714,1715],{"class":1264},"now",[223,1717,1718],{"class":1418},"() ",[223,1720,1627],{"class":1260},[223,1722,1723],{"class":1512}," 1000",[223,1725,1654],{"class":1418},[223,1727,1728],{"class":1260},"-",[223,1730,1731],{"class":1264}," Number",[223,1733,1326],{"class":1418},[223,1735,1618],{"class":1178},[223,1737,1738],{"class":1418},")) ",[223,1740,1741],{"class":1260},">",[223,1743,1744],{"class":1512}," 300",[223,1746,1654],{"class":1418},[223,1748,1675],{"class":1174},[223,1750,1679],{"class":1678},[223,1752,1214],{"class":229},[223,1754,1756],{"class":225,"line":1755},19,[223,1757,1247],{"emptyLinePlaceholder":1246},[223,1759,1761,1763,1766,1768,1770,1772,1775],{"class":225,"line":1760},20,[223,1762,1403],{"class":1252},[223,1764,1765],{"class":1256}," signedPayload",[223,1767,1261],{"class":1260},[223,1769,1380],{"class":1178},[223,1771,1024],{"class":229},[223,1773,1774],{"class":1264},"concat",[223,1776,1777],{"class":1418},"([\n",[223,1779,1781,1784,1786,1789,1791,1794,1796,1799,1801,1804,1806,1808,1811,1813,1815],{"class":225,"line":1780},21,[223,1782,1783],{"class":1178},"    Buffer",[223,1785,1024],{"class":229},[223,1787,1788],{"class":1264},"from",[223,1790,1326],{"class":1418},[223,1792,1793],{"class":248},"`${",[223,1795,1618],{"class":1178},[223,1797,1798],{"class":248},"}",[223,1800,1024],{"class":252},[223,1802,1803],{"class":248},"`",[223,1805,1182],{"class":229},[223,1807,249],{"class":248},[223,1809,1810],{"class":252},"utf8",[223,1812,243],{"class":248},[223,1814,1335],{"class":1418},[223,1816,258],{"class":229},[223,1818,1820,1823],{"class":225,"line":1819},22,[223,1821,1822],{"class":1178},"    rawBody",[223,1824,258],{"class":229},[223,1826,1828,1831],{"class":225,"line":1827},23,[223,1829,1830],{"class":1418},"  ])",[223,1832,1214],{"class":229},[223,1834,1836],{"class":225,"line":1835},24,[223,1837,1247],{"emptyLinePlaceholder":1246},[223,1839,1841,1844,1846,1848,1851,1853,1855,1857,1859,1861],{"class":225,"line":1840},25,[223,1842,1843],{"class":1174},"  return",[223,1845,1276],{"class":1178},[223,1847,1024],{"class":229},[223,1849,1850],{"class":1264},"some",[223,1852,1326],{"class":1418},[223,1854,1326],{"class":229},[223,1856,1332],{"class":1331},[223,1858,1335],{"class":229},[223,1860,1349],{"class":1252},[223,1862,378],{"class":229},[223,1864,1866,1869,1872,1874,1876,1878,1880,1883,1885,1887,1889],{"class":225,"line":1865},26,[223,1867,1868],{"class":1252},"    const",[223,1870,1871],{"class":1256}," expected",[223,1873,1261],{"class":1260},[223,1875,1223],{"class":1264},[223,1877,1326],{"class":1418},[223,1879,243],{"class":248},[223,1881,1882],{"class":252},"sha256",[223,1884,243],{"class":248},[223,1886,1182],{"class":229},[223,1888,1340],{"class":1178},[223,1890,1891],{"class":1418},")\n",[223,1893,1895,1898,1901,1903,1906],{"class":225,"line":1894},27,[223,1896,1897],{"class":229},"      .",[223,1899,1900],{"class":1264},"update",[223,1902,1326],{"class":1418},[223,1904,1905],{"class":1178},"signedPayload",[223,1907,1891],{"class":1418},[223,1909,1911,1913,1916,1918],{"class":225,"line":1910},28,[223,1912,1897],{"class":229},[223,1914,1915],{"class":1264},"digest",[223,1917,1267],{"class":1418},[223,1919,1214],{"class":229},[223,1921,1923],{"class":225,"line":1922},29,[223,1924,1247],{"emptyLinePlaceholder":1246},[223,1926,1928,1931,1933,1935,1937,1939,1941,1944,1946,1948],{"class":225,"line":1927},30,[223,1929,1930],{"class":1174},"    return",[223,1932,1525],{"class":1178},[223,1934,1024],{"class":229},[223,1936,1850],{"class":1264},[223,1938,1326],{"class":1418},[223,1940,1326],{"class":229},[223,1942,1943],{"class":1331},"hex",[223,1945,1335],{"class":229},[223,1947,1349],{"class":1252},[223,1949,378],{"class":229},[223,1951,1953,1956,1958,1960,1962,1964,1967,1970,1972,1975,1977,1979,1983,1985,1987,1989,1991,1993,1995,1997],{"class":225,"line":1952},31,[223,1954,1955],{"class":1174},"      if",[223,1957,1612],{"class":1418},[223,1959,1615],{"class":1260},[223,1961,1627],{"class":248},[223,1963,1630],{"class":1174},[223,1965,1966],{"class":236},"[",[223,1968,1969],{"class":1633},"0-9a-f",[223,1971,1318],{"class":236},[223,1973,1974],{"class":1260},"{64}",[223,1976,1640],{"class":1174},[223,1978,1627],{"class":248},[223,1980,1982],{"class":1981},"sw1J6","i",[223,1984,1024],{"class":229},[223,1986,1647],{"class":1264},[223,1988,1326],{"class":1418},[223,1990,1943],{"class":1178},[223,1992,1738],{"class":1418},[223,1994,1675],{"class":1174},[223,1996,1679],{"class":1678},[223,1998,1214],{"class":229},[223,2000,2002,2005,2008,2010,2012,2014,2016,2018,2020,2022,2024,2026,2028,2030],{"class":225,"line":2001},32,[223,2003,2004],{"class":1252},"      const",[223,2006,2007],{"class":1256}," actual",[223,2009,1261],{"class":1260},[223,2011,1380],{"class":1178},[223,2013,1024],{"class":229},[223,2015,1788],{"class":1264},[223,2017,1326],{"class":1418},[223,2019,1943],{"class":1178},[223,2021,1182],{"class":229},[223,2023,249],{"class":248},[223,2025,1943],{"class":252},[223,2027,243],{"class":248},[223,2029,1335],{"class":1418},[223,2031,1214],{"class":229},[223,2033,2035,2038,2040,2042,2044,2046,2048,2050,2052,2055,2057,2059,2062,2064,2066,2068],{"class":225,"line":2034},33,[223,2036,2037],{"class":1174},"      return",[223,2039,2007],{"class":1178},[223,2041,1024],{"class":229},[223,2043,1664],{"class":1256},[223,2045,1667],{"class":1260},[223,2047,1871],{"class":1178},[223,2049,1024],{"class":229},[223,2051,1664],{"class":1256},[223,2053,2054],{"class":1260}," &&",[223,2056,1228],{"class":1264},[223,2058,1326],{"class":1418},[223,2060,2061],{"class":1178},"actual",[223,2063,1182],{"class":229},[223,2065,1871],{"class":1178},[223,2067,1335],{"class":1418},[223,2069,1214],{"class":229},[223,2071,2073,2076,2078],{"class":225,"line":2072},34,[223,2074,2075],{"class":229},"    }",[223,2077,1335],{"class":1418},[223,2079,1214],{"class":229},[223,2081,2083,2086,2088],{"class":225,"line":2082},35,[223,2084,2085],{"class":229},"  }",[223,2087,1335],{"class":1418},[223,2089,1214],{"class":229},[223,2091,2093],{"class":225,"line":2092},36,[223,2094,431],{"class":229},[223,2096,2098],{"class":225,"line":2097},37,[223,2099,1247],{"emptyLinePlaceholder":1246},[223,2101,2103,2105,2108,2110,2112,2116,2118,2120,2122,2124,2126,2128],{"class":225,"line":2102},38,[223,2104,266],{"class":1252},[223,2106,2107],{"class":1379}," WebhookEvent",[223,2109,1261],{"class":1260},[223,2111,1185],{"class":229},[223,2113,2115],{"class":2114},"sucvu"," id",[223,2117,175],{"class":1260},[223,2119,1346],{"class":387},[223,2121,1423],{"class":229},[223,2123,1188],{"class":2114},[223,2125,175],{"class":1260},[223,2127,1346],{"class":387},[223,2129,2130],{"class":229}," };\n",[223,2132,2134],{"class":225,"line":2133},39,[223,2135,1247],{"emptyLinePlaceholder":1246},[223,2137,2139,2142,2145,2148,2150,2153,2155,2157,2159,2161,2164,2167,2170,2172],{"class":225,"line":2138},40,[223,2140,2141],{"class":1252},"async",[223,2143,2144],{"class":1252}," function",[223,2146,2147],{"class":1264}," persistForProcessing",[223,2149,1326],{"class":229},[223,2151,2152],{"class":1331},"event",[223,2154,175],{"class":1260},[223,2156,2107],{"class":1379},[223,2158,1335],{"class":229},[223,2160,175],{"class":1260},[223,2162,2163],{"class":1379}," Promise",[223,2165,2166],{"class":229},"\u003C",[223,2168,2169],{"class":387},"void",[223,2171,1741],{"class":229},[223,2173,378],{"class":229},[223,2175,2177],{"class":225,"line":2176},41,[223,2178,2180],{"class":2179},"sutJx","  \u002F\u002F Insert event.id with a unique constraint and enqueue the event atomically.\n",[223,2182,2184],{"class":225,"line":2183},42,[223,2185,2186],{"class":2179},"  \u002F\u002F A worker—not this request—hydrates available resources and runs workflows.\n",[223,2188,2190,2193,2195,2198,2200,2202,2204],{"class":225,"line":2189},43,[223,2191,2192],{"class":1178},"  console",[223,2194,1024],{"class":229},[223,2196,2197],{"class":1264},"log",[223,2199,1326],{"class":1418},[223,2201,2152],{"class":1178},[223,2203,1335],{"class":1418},[223,2205,1214],{"class":229},[223,2207,2209],{"class":225,"line":2208},44,[223,2210,431],{"class":229},[223,2212,2214],{"class":225,"line":2213},45,[223,2215,1247],{"emptyLinePlaceholder":1246},[223,2217,2219,2222,2224,2227],{"class":225,"line":2218},46,[223,2220,2221],{"class":1178},"app",[223,2223,1024],{"class":229},[223,2225,2226],{"class":1264},"post",[223,2228,2229],{"class":1178},"(\n",[223,2231,2233,2235,2238,2240],{"class":225,"line":2232},47,[223,2234,237],{"class":248},[223,2236,2237],{"class":252},"\u002Fwebhooks\u002Fnewledger",[223,2239,243],{"class":248},[223,2241,258],{"class":229},[223,2243,2245,2248,2250,2253,2255,2258,2260,2262,2264,2267,2269,2271,2273],{"class":225,"line":2244},48,[223,2246,2247],{"class":1178},"  express",[223,2249,1024],{"class":229},[223,2251,2252],{"class":1264},"raw",[223,2254,1326],{"class":1178},[223,2256,2257],{"class":229},"{",[223,2259,1188],{"class":1418},[223,2261,175],{"class":229},[223,2263,249],{"class":248},[223,2265,2266],{"class":252},"application\u002Fjson",[223,2268,243],{"class":248},[223,2270,1201],{"class":229},[223,2272,1335],{"class":1178},[223,2274,258],{"class":229},[223,2276,2278,2281,2283,2286,2288,2290,2292,2295,2297,2299,2301,2303],{"class":225,"line":2277},49,[223,2279,2280],{"class":1252},"  async",[223,2282,1612],{"class":229},[223,2284,2285],{"class":1331},"req",[223,2287,175],{"class":1260},[223,2289,1191],{"class":1379},[223,2291,1182],{"class":229},[223,2293,2294],{"class":1331}," res",[223,2296,175],{"class":1260},[223,2298,1198],{"class":1379},[223,2300,1335],{"class":229},[223,2302,1349],{"class":1252},[223,2304,378],{"class":229},[223,2306,2308,2310,2313,2315,2318,2320,2323,2325,2327,2329,2331,2333],{"class":225,"line":2307},50,[223,2309,1868],{"class":1252},[223,2311,2312],{"class":1256}," signature",[223,2314,1261],{"class":1260},[223,2316,2317],{"class":1178}," req",[223,2319,1024],{"class":229},[223,2321,2322],{"class":1264},"get",[223,2324,1326],{"class":1418},[223,2326,243],{"class":248},[223,2328,1076],{"class":252},[223,2330,243],{"class":248},[223,2332,1335],{"class":1418},[223,2334,1214],{"class":229},[223,2336,2338,2341,2343,2345,2348,2350,2352,2355,2357,2359,2361,2364,2366,2368,2370],{"class":225,"line":2337},51,[223,2339,2340],{"class":1174},"    if",[223,2342,1612],{"class":1418},[223,2344,1615],{"class":1260},[223,2346,2347],{"class":1178},"signature",[223,2349,1621],{"class":1260},[223,2351,1624],{"class":1260},[223,2353,2354],{"class":1264},"verifyWebhook",[223,2356,1326],{"class":1418},[223,2358,2285],{"class":1178},[223,2360,1024],{"class":229},[223,2362,2363],{"class":1178},"body",[223,2365,1182],{"class":229},[223,2367,2312],{"class":1178},[223,2369,1738],{"class":1418},[223,2371,230],{"class":229},[223,2373,2375,2377,2379,2381,2384,2386,2389,2391,2393,2396,2398,2400,2403,2405,2407],{"class":225,"line":2374},52,[223,2376,2037],{"class":1174},[223,2378,2294],{"class":1178},[223,2380,1024],{"class":229},[223,2382,2383],{"class":1264},"status",[223,2385,1326],{"class":1418},[223,2387,2388],{"class":1512},"401",[223,2390,1335],{"class":1418},[223,2392,1024],{"class":229},[223,2394,2395],{"class":1264},"send",[223,2397,1326],{"class":1418},[223,2399,243],{"class":248},[223,2401,2402],{"class":252},"Invalid signature",[223,2404,243],{"class":248},[223,2406,1335],{"class":1418},[223,2408,1214],{"class":229},[223,2410,2412],{"class":225,"line":2411},53,[223,2413,2414],{"class":229},"    }\n",[223,2416,2418],{"class":225,"line":2417},54,[223,2419,1247],{"emptyLinePlaceholder":1246},[223,2421,2423,2425,2428,2430,2433,2435,2438,2440,2442,2444,2446,2448,2451,2453,2455,2457,2459,2461,2464,2466],{"class":225,"line":2422},55,[223,2424,1868],{"class":1252},[223,2426,2427],{"class":1256}," event",[223,2429,1261],{"class":1260},[223,2431,2432],{"class":1256}," JSON",[223,2434,1024],{"class":229},[223,2436,2437],{"class":1264},"parse",[223,2439,1326],{"class":1418},[223,2441,2285],{"class":1178},[223,2443,1024],{"class":229},[223,2445,2363],{"class":1178},[223,2447,1024],{"class":229},[223,2449,2450],{"class":1264},"toString",[223,2452,1326],{"class":1418},[223,2454,243],{"class":248},[223,2456,1810],{"class":252},[223,2458,243],{"class":248},[223,2460,1738],{"class":1418},[223,2462,2463],{"class":1174},"as",[223,2465,2107],{"class":1379},[223,2467,1214],{"class":229},[223,2469,2471],{"class":225,"line":2470},56,[223,2472,1247],{"emptyLinePlaceholder":1246},[223,2474,2476,2478,2480,2482,2484,2486,2488,2490,2493,2495,2497],{"class":225,"line":2475},57,[223,2477,2340],{"class":1174},[223,2479,1612],{"class":1418},[223,2481,2152],{"class":1178},[223,2483,1024],{"class":229},[223,2485,266],{"class":1178},[223,2487,1667],{"class":1260},[223,2489,249],{"class":248},[223,2491,2492],{"class":252},"webhook.endpoint.verification",[223,2494,243],{"class":248},[223,2496,1654],{"class":1418},[223,2498,230],{"class":229},[223,2500,2502,2504,2506,2508,2511,2513,2516,2518],{"class":225,"line":2501},58,[223,2503,2037],{"class":1174},[223,2505,2294],{"class":1178},[223,2507,1024],{"class":229},[223,2509,2510],{"class":1264},"sendStatus",[223,2512,1326],{"class":1418},[223,2514,2515],{"class":1512},"204",[223,2517,1335],{"class":1418},[223,2519,1214],{"class":229},[223,2521,2523],{"class":225,"line":2522},59,[223,2524,2414],{"class":229},[223,2526,2528],{"class":225,"line":2527},60,[223,2529,1247],{"emptyLinePlaceholder":1246},[223,2531,2533],{"class":225,"line":2532},61,[223,2534,2535],{"class":2179},"    \u002F\u002F Keep this durable handoff short; never hydrate or run business logic here.\n",[223,2537,2539,2542,2544,2546,2548,2550],{"class":225,"line":2538},62,[223,2540,2541],{"class":1174},"    await",[223,2543,2147],{"class":1264},[223,2545,1326],{"class":1418},[223,2547,2152],{"class":1178},[223,2549,1335],{"class":1418},[223,2551,1214],{"class":229},[223,2553,2555,2557,2559,2561,2563,2565,2567,2569],{"class":225,"line":2554},63,[223,2556,1930],{"class":1174},[223,2558,2294],{"class":1178},[223,2560,1024],{"class":229},[223,2562,2510],{"class":1264},[223,2564,1326],{"class":1418},[223,2566,2515],{"class":1512},[223,2568,1335],{"class":1418},[223,2570,1214],{"class":229},[223,2572,2574],{"class":225,"line":2573},64,[223,2575,2576],{"class":229},"  },\n",[223,2578,2580,2582],{"class":225,"line":2579},65,[223,2581,1335],{"class":1178},[223,2583,1214],{"class":229},[197,2585,2588],{"title":2586,"tone":2587},"Optional custom headers","info",[12,2589,2590,2591,2594],{},"Optionally attach up to three encrypted ",[49,2592,2593],{},"X-*"," headers. Treat these as secondary authentication; signature verification remains mandatory.",[99,2596,2598],{"id":2597},"rotate-a-signing-secret-without-interrupting-delivery","Rotate a signing secret without interrupting delivery",[12,2600,2601,2602,2605],{},"NewLedger keeps the previous secret usable for 24 hours through ",[172,2603,2604],{},"dual-signing",". It does not choose one secret or the other: during the overlap, every production delivery is signed by both.",[214,2607,2610],{"className":2608,"code":2609,"language":1054,"meta":219},[1052],"Webhook-Signature: t=\u003Cunix-seconds>;v1=\u003Ccurrent-signature>;v1=\u003Cprevious-signature>\n",[49,2611,2609],{"__ignoreMap":219},[12,2613,2614,2615,2618,2619,2621],{},"Both signatures use the same timestamp and exact raw request body. The receiver calculates the expected signature with each secret it currently trusts and accepts the request when ",[172,2616,2617],{},"either"," supplied ",[49,2620,1129],{}," value matches.",[21,2623,2624,2634],{},[24,2625,2626],{},[27,2627,2628,2631],{},[30,2629,2630],{},"Rotation behavior",[30,2632,2633],{},"What it means",[37,2635,2636,2644,2652,2660,2668,2676],{},[27,2637,2638,2641],{},[42,2639,2640],{},"New secret becomes current",[42,2642,2643],{},"Use it for all new receiver deployments immediately",[27,2645,2646,2649],{},[42,2647,2648],{},"Previous secret remains valid for 24 hours",[42,2650,2651],{},"Existing deployments can continue verifying deliveries during rollout",[27,2653,2654,2657],{},[42,2655,2656],{},"At most two secrets are active",[42,2658,2659],{},"Rotating again replaces the previous secret and starts a new 24-hour window",[27,2661,2662,2665],{},[42,2663,2664],{},"Secret reveal returns the current secret only",[42,2666,2667],{},"Keep the previous value in your secret manager until the overlap ends",[27,2669,2670,2673],{},[42,2671,2672],{},"Previous secret expires automatically",[42,2674,2675],{},"After 24 hours, deliveries contain only the current signature",[27,2677,2678,2681],{},[42,2679,2680],{},"Endpoint verification uses the current secret",[42,2682,2683],{},"Test new endpoint configuration with the newly rotated value",[12,2685,2686],{},"Recommended rollout:",[1119,2688,2689,2692,2695,2698,2701],{},[107,2690,2691],{},"Rotate the endpoint secret and save the new value immediately.",[107,2693,2694],{},"Add the new secret to the receiver while retaining the previous secret.",[107,2696,2697],{},"Deploy verification that checks both trusted secrets.",[107,2699,2700],{},"Confirm live requests verify with the current signature.",[107,2702,2703],{},"Remove the previous secret after the 24-hour overlap.",[197,2705,2707],{"title":2706,"tone":2587},"Rotation changes signing, not the event",[12,2708,2709],{},"The timestamp, raw body, event ID, and payload stay the same. Only the signature list expands during the overlap, so processing and deduplication behavior do not change.",[16,2711,143],{"id":2712},"delivery-retries",[12,2714,2715],{},"NewLedger makes one immediate attempt followed by up to six automatic retries. Each delay is measured from the preceding failed attempt and receives independent jitter.",[214,2717,2720],{"className":2718,"code":2719,"language":1054,"meta":219},[1052],"Immediate → 1 min → 10 min → 1 hr → 8 hr → 24 hr → 48 hr\n",[49,2721,2719],{"__ignoreMap":219},[21,2723,2724,2734],{},[24,2725,2726],{},[27,2727,2728,2731],{},[30,2729,2730],{},"Result",[30,2732,2733],{},"Delivery behavior",[37,2735,2736,2744,2760,2769,2780],{},[27,2737,2738,2741],{},[42,2739,2740],{},"Network failure",[42,2742,2743],{},"Retry",[27,2745,2746,2758],{},[42,2747,2748,2751,2752,2751,2755],{},[49,2749,2750],{},"408",", ",[49,2753,2754],{},"425",[49,2756,2757],{},"429",[42,2759,2743],{},[27,2761,2762,2767],{},[42,2763,2764],{},[49,2765,2766],{},"5xx",[42,2768,2743],{},[27,2770,2771,2777],{},[42,2772,2773,2774],{},"Other ",[49,2775,2776],{},"4xx",[42,2778,2779],{},"Terminal failure",[27,2781,2782,2786],{},[42,2783,47,2784],{},[49,2785,51],{},[42,2787,2788],{},"Acknowledged",[12,2790,2791,2792,2795,2796,2798,2799,1024],{},"A valid ",[49,2793,2794],{},"Retry-After"," response on ",[49,2797,2757],{}," is honored within the remaining retry and retention window. Every retry retains the original event ID and stored payload while incrementing ",[49,2800,1098],{},[16,2802,149],{"id":2803},"timeouts-and-redirects",[21,2805,2806,2823],{},[24,2807,2808],{},[27,2809,2810,2813,2817,2820],{},[30,2811,2812],{},"Request",[30,2814,2816],{"align":2815},"right","Connection timeout",[30,2818,2819],{"align":2815},"Total timeout",[30,2821,2822],{},"Redirects",[37,2824,2825,2838],{},[27,2826,2827,2830,2833,2835],{},[42,2828,2829],{},"Production delivery",[42,2831,2832],{"align":2815},"5 seconds",[42,2834,87],{"align":2815},[42,2836,2837],{},"Disabled",[27,2839,2840,2843,2846,2848],{},[42,2841,2842],{},"Endpoint verification",[42,2844,2845],{"align":2815},"3 seconds",[42,2847,2832],{"align":2815},[42,2849,2837],{},[12,2851,2852,2853,2856,2857,2859,2860,2862,2863,2865],{},"Manage endpoints under ",[172,2854,2855],{},"Settings → Webhooks",". Endpoint verification uses the same signed request path and HMAC headers as production delivery, but sends the distinct ",[49,2858,2492],{}," event. Creating an endpoint places it in ",[49,2861,1033],{},"; a ",[49,2864,51],{}," response activates it. Changing the URL requires verification again.",[197,2867,2869],{"title":2868,"tone":2587},"The webhook is a signal",[12,2870,2871,2872,2875,2876,2878],{},"After verification, retrieve current state only when that resource has a supported read operation. Do not use a payment or application ",[49,2873,2874],{},"resource.id"," as an invoice, bill, or credit-note ID. Pair those notification-only events with ",[49,2877,543],{}," subscriptions or list-based reconciliation when current document state is required.",[16,2880,155],{"id":2881},"idempotent-processing",[12,2883,2884],{},"Event deduplication protects the receiver. Each downstream action should also have an idempotency key so a repeated delivery cannot repeat the outcome.",[214,2886,2889],{"className":2887,"code":2888,"language":1054,"meta":219},[1052],"evt_123:activate_subscription\nevt_123:notify_account_owner\nevt_123:refresh_revenue_projection\n",[49,2890,2888],{"__ignoreMap":219},[12,2892,2893],{},"Use a database uniqueness constraint or pass the key to a downstream API that supports idempotency. Do not rely on an in-memory cache.",[21,2895,2896,2906],{},[24,2897,2898],{},[27,2899,2900,2903],{},[30,2901,2902],{},"Workflow",[30,2904,2905],{},"Out-of-order strategy",[37,2907,2908,2916,2927],{},[27,2909,2910,2913],{},[42,2911,2912],{},"Dashboard, CRM mirror, current status",[42,2914,2915],{},"Fetch the latest resource from the API",[27,2917,2918,2921],{},[42,2919,2920],{},"Payment or application event",[42,2922,2923,2924,2926],{},"Treat as notification-only; pair with ",[49,2925,543],{}," or reconcile through list APIs",[27,2928,2929,2932],{},[42,2930,2931],{},"Transition-specific automation",[42,2933,2934],{},"Handle each event type separately and idempotently; do not infer ordering from a resource version",[16,2936,161],{"id":2937},"endpoint-health-and-recovery",[12,2939,2940],{},"Delivery history keeps the immutable request payload and attempt diagnostics. A manual resend creates a new delivery record; it does not rewrite history.",[12,2942,2943],{},"After three separate events exhaust their retry schedules without an intervening success, the endpoint pauses. A successful event resets that consecutive-exhaustion count.",[12,2945,2946],{},"Resuming enables new subscribed events. It does not backfill the paused period. Recover by reconciling against company-scoped resource APIs or ledger exports, then resume live delivery.",[197,2948,2951],{"title":2949,"tone":2950},"The ledger remains the recovery source","success",[12,2952,2953,2954,2958,2959,1024],{},"Webhook history helps diagnose delivery. The NewLedger API and ledger exports are the authoritative sources for rebuilding missing or stale state. See how those boundaries fit together in ",[110,2955,2957],{"href":2956},"\u002Fplatform-architecture","platform architecture"," and how NewLedger protects them in ",[110,2960,2962],{"href":2961},"\u002Fsecurity-and-compliance","security and compliance",[16,2964,167],{"id":2965},"production-checklist",[104,2967,2970,2979,2985,2991,2997,3006,3015,3021,3027,3033,3039,3045],{"className":2968},[2969],"contains-task-list",[107,2971,2974,2978],{"className":2972},[2973],"task-list-item",[2975,2976],"input",{"disabled":1246,"type":2977},"checkbox"," Verify the raw body before parsing JSON",[107,2980,2982,2984],{"className":2981},[2973],[2975,2983],{"disabled":1246,"type":2977}," Enforce the five-minute timestamp tolerance",[107,2986,2988,2990],{"className":2987},[2973],[2975,2989],{"disabled":1246,"type":2977}," Store endpoint secrets outside source control",[107,2992,2994,2996],{"className":2993},[2973],[2975,2995],{"disabled":1246,"type":2977}," Add a unique constraint for the event ID",[107,2998,3000,3002,3003,3005],{"className":2999},[2973],[2975,3001],{"disabled":1246,"type":2977}," Return ",[49,3004,51],{}," after accepting a valid notification",[107,3007,3009,3011,3012,3014],{"className":3008},[2973],[2975,3010],{"disabled":1246,"type":2977}," Accept ",[49,3013,2492],{}," without running a business workflow",[107,3016,3018,3020],{"className":3017},[2973],[2975,3019],{"disabled":1246,"type":2977}," Move hydration and business processing outside the request path",[107,3022,3024,3026],{"className":3023},[2973],[2975,3025],{"disabled":1246,"type":2977}," Make each business effect idempotent",[107,3028,3030,3032],{"className":3029},[2973],[2975,3031],{"disabled":1246,"type":2977}," Tolerate out-of-order delivery",[107,3034,3036,3038],{"className":3035},[2973],[2975,3037],{"disabled":1246,"type":2977}," Monitor failed processing, exhausted delivery retries, and paused endpoints",[107,3040,3042,3044],{"className":3041},[2973],[2975,3043],{"disabled":1246,"type":2977}," Test duplicate, delayed, reordered, and replayed events",[107,3046,3048,3050],{"className":3047},[2973],[2975,3049],{"disabled":1246,"type":2977}," Document the reconciliation procedure",[12,3052,3053,3054,3058],{},"For embedded deployments, the same webhook contract can sit behind a ",[110,3055,3057],{"href":3056},"\u002Fwhite-label-accounting-software","white-label accounting platform"," without exposing implementation-specific headers to customers.",[3060,3061,3062],"style",{},"html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sseR_, html code.shiki .sseR_{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}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);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}",{"title":219,"searchDepth":233,"depth":233,"links":3064},[3065,3068,3069,3070,3073,3077,3078,3079,3080,3081],{"id":18,"depth":233,"text":19,"children":3066},[3067],{"id":101,"depth":261,"text":102},{"id":209,"depth":233,"text":113},{"id":514,"depth":233,"text":119},{"id":556,"depth":233,"text":125,"children":3071},[3072],{"id":1012,"depth":261,"text":1013},{"id":1036,"depth":233,"text":131,"children":3074},[3075,3076],{"id":1154,"depth":261,"text":1155},{"id":2597,"depth":261,"text":2598},{"id":2712,"depth":233,"text":143},{"id":2803,"depth":233,"text":149},{"id":2881,"depth":233,"text":155},{"id":2937,"depth":233,"text":161},{"id":2965,"depth":233,"text":167},"engineering",null,[7],{"src":3086,"alt":3087,"credit":3088},"blog\u002Faccounting-webhooks-reliable-workflows.webp","A secure accounting event stream connecting a ledger to several business workflows","NewLedger Editorial","2026-08-22",{"heading":3091,"description":3092,"primaryLabel":3093,"primaryAction":3094,"secondaryLabel":3095,"secondaryPath":528},"Build your accounting integration","Create a NewLedger workspace, then open Settings → Webhooks to configure and test signed delivery.","Create a workspace","signup","Explore API documentation","md",false,{},"\u002Fblog\u002F2026\u002F08\u002F22-accounting-webhooks","10",{"title":3102,"description":3103},"Accounting Webhooks Integration Guide | NewLedger","Build a reliable accounting webhook integration with NewLedger event types, HMAC-SHA256 signature verification, retry schedules, timeouts, idempotency, and recovery.","accounting-webhooks-integration-guide","published","blog\u002F2026\u002F08\u002F22-accounting-webhooks","Build a secure, reliable accounting API integration with NewLedger event types, signature verification, retries, timeouts, and recovery.",[3109,3110,3111,3112,3113,3114,3115,3116],"accounting-webhooks","webhook-integration","webhook-signature-verification","accounting-api","api-integration","event-driven-accounting","automation","newledger","2026-08-23","hd5M0XybXpNpwbQzi9KTMx4kypHVrKHWCYLxB0wcFSE",[],1787479696280]