[{"data":1,"prerenderedAt":2370},["ShallowReactive",2],{"docs-nav":3,"docs-\u002Fdocs\u002Fapi\u002Fwebhooks":70},[4,10,14,19,23,26,29,33,36,40,43,47,50,54,58,62,66],{"title":5,"path":6,"order":7,"section":8,"group":9},"Concepts","\u002Fdocs\u002Fapi\u002Fconcepts",1,"api",null,{"title":11,"path":12,"order":7,"section":13,"group":9},"Introduction","\u002Fdocs","general",{"title":15,"path":16,"order":7,"section":17,"group":18},"Usage","\u002Fdocs\u002Fsdk\u002Fusage","sdk","Script",{"title":20,"path":21,"order":22,"section":8,"group":9},"\u002Fv1\u002Fme","\u002Fdocs\u002Fapi\u002Fme",2,{"title":24,"path":25,"order":22,"section":13,"group":9},"Getting started","\u002Fdocs\u002Fgetting-started",{"title":24,"path":27,"order":22,"section":17,"group":28},"\u002Fdocs\u002Fsdk\u002Fpackage","Package",{"title":30,"path":31,"order":32,"section":8,"group":9},"\u002Fv1\u002Fsubscribe","\u002Fdocs\u002Fapi\u002Fsubscribe",3,{"title":34,"path":35,"order":32,"section":17,"group":28},"Browser client","\u002Fdocs\u002Fsdk\u002Fpackage\u002Fclient",{"title":37,"path":38,"order":39,"section":8,"group":9},"\u002Fv1\u002Funsubscribe","\u002Fdocs\u002Fapi\u002Funsubscribe",4,{"title":41,"path":42,"order":39,"section":17,"group":28},"Server client","\u002Fdocs\u002Fsdk\u002Fpackage\u002Fserver",{"title":44,"path":45,"order":46,"section":8,"group":9},"\u002Fv1\u002Fevents","\u002Fdocs\u002Fapi\u002Fevents",5,{"title":48,"path":49,"order":46,"section":17,"group":28},"Types","\u002Fdocs\u002Fsdk\u002Fpackage\u002Ftypes",{"title":51,"path":52,"order":53,"section":8,"group":9},"\u002Fv1\u002Fsend","\u002Fdocs\u002Fapi\u002Fsend",6,{"title":55,"path":56,"order":57,"section":8,"group":9},"\u002Fv1\u002Fbroadcasts","\u002Fdocs\u002Fapi\u002Fbroadcasts",7,{"title":59,"path":60,"order":61,"section":8,"group":9},"\u002Fv1\u002Fgroups","\u002Fdocs\u002Fapi\u002Fgroups",8,{"title":63,"path":64,"order":65,"section":8,"group":9},"\u002Fv1\u002Fsubscribers","\u002Fdocs\u002Fapi\u002Fsubscribers",9,{"title":67,"path":68,"order":69,"section":8,"group":9},"Webhooks","\u002Fdocs\u002Fapi\u002Fwebhooks",10,{"id":71,"title":67,"apiModule":9,"body":72,"description":2363,"extension":2364,"generated":2365,"group":9,"meta":2366,"navigation":634,"order":69,"path":68,"section":8,"seo":2367,"stem":2368,"__hash__":2369},"docs\u002Fdocs\u002Fapi\u002Fwebhooks.md",{"type":73,"value":74,"toc":2350},"minimark",[75,79,88,93,162,168,172,175,241,245,422,451,492,547,551,554,562,572,576,583,588,1213,1217,1222,1934,1938,2318,2322,2329,2332,2336,2346],[76,77,67],"h1",{"id":78},"webhooks",[80,81,82,83,87],"p",{},"LitePush POSTs a JSON payload to a URL on your server every time something happens to one of your notifications. Configure the URL in ",[84,85,86],"strong",{},"Project → Settings → Webhooks"," (Plus, Pro, and Max plans). The signing secret is auto-generated when the project is created and shown there too.",[89,90,92],"h2",{"id":91},"url-requirements","URL requirements",[94,95,96,108,146,156],"ul",{},[97,98,99,102,103,107],"li",{},[84,100,101],{},"HTTPS only."," Plain ",[104,105,106],"code",{},"http:\u002F\u002F"," is rejected.",[97,109,110,113,114,117,118,121,122,117,125,117,128,131,132,135,136,117,139,117,142,145],{},[84,111,112],{},"Publicly reachable hostname or IP."," Loopback (",[104,115,116],{},"localhost",", ",[104,119,120],{},"127.x","), RFC 1918 private ranges (",[104,123,124],{},"10.x",[104,126,127],{},"172.16–31.x",[104,129,130],{},"192.168.x","), link-local (",[104,133,134],{},"169.254.x","), and internal-style suffixes (",[104,137,138],{},".internal",[104,140,141],{},".local",[104,143,144],{},".lan",", etc.) are rejected to prevent webhooks from being used to probe internal networks.",[97,147,148,151,152,155],{},[84,149,150],{},"No credentials in the URL."," Use ",[104,153,154],{},"Authorization"," headers on the receiving side instead.",[97,157,158,161],{},[84,159,160],{},"No redirects."," Your endpoint must respond directly; 3xx responses are treated as a delivery failure.",[80,163,164,165,167],{},"If your receiver runs behind a firewall, expose it via a tunnel (e.g. Cloudflare Tunnel) or use a hosted endpoint for testing — ",[104,166,116],{}," URLs won't work even in development.",[89,169,171],{"id":170},"when-webhooks-fire","When webhooks fire",[80,173,174],{},"Four event types:",[176,177,178,191],"table",{},[179,180,181],"thead",{},[182,183,184,188],"tr",{},[185,186,187],"th",{},"Type",[185,189,190],{},"Fires when",[192,193,194,205,221,231],"tbody",{},[182,195,196,202],{},[197,198,199],"td",{},[104,200,201],{},"delivered",[197,203,204],{},"LitePush successfully handed the push to the browser's push gateway.",[182,206,207,212],{},[197,208,209],{},[104,210,211],{},"clicked",[197,213,214,215,220],{},"The user clicked the notification (your service worker beaconed it via ",[216,217,218],"a",{"href":45},[104,219,44],{},").",[182,222,223,228],{},[197,224,225],{},[104,226,227],{},"dismissed",[197,229,230],{},"The user dismissed without clicking.",[182,232,233,238],{},[197,234,235],{},[104,236,237],{},"failed",[197,239,240],{},"The push could not be delivered — endpoint gone, gateway error, etc.",[89,242,244],{"id":243},"payload-shape","Payload shape",[246,247,252],"pre",{"className":248,"code":249,"language":250,"meta":251,"style":251},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"id\": \"evt_01HXM...\",\n  \"type\": \"delivered\",\n  \"project_id\": \"prj_01HXM...\",\n  \"broadcast_id\": \"bdc_01HXM...\",\n  \"subscriber_id\": \"sub_01HXM...\",\n  \"external_id\": \"user_42\",\n  \"meta\": null,\n  \"created_at\": 1716762345123\n}\n","json","",[104,253,254,262,289,308,328,348,368,388,402,417],{"__ignoreMap":251},[255,256,258],"span",{"class":257,"line":7},"line",[255,259,261],{"class":260},"sMK4o","{\n",[255,263,264,267,271,274,277,280,284,286],{"class":257,"line":22},[255,265,266],{"class":260},"  \"",[255,268,270],{"class":269},"spNyl","id",[255,272,273],{"class":260},"\"",[255,275,276],{"class":260},":",[255,278,279],{"class":260}," \"",[255,281,283],{"class":282},"sfazB","evt_01HXM...",[255,285,273],{"class":260},[255,287,288],{"class":260},",\n",[255,290,291,293,296,298,300,302,304,306],{"class":257,"line":32},[255,292,266],{"class":260},[255,294,295],{"class":269},"type",[255,297,273],{"class":260},[255,299,276],{"class":260},[255,301,279],{"class":260},[255,303,201],{"class":282},[255,305,273],{"class":260},[255,307,288],{"class":260},[255,309,310,312,315,317,319,321,324,326],{"class":257,"line":39},[255,311,266],{"class":260},[255,313,314],{"class":269},"project_id",[255,316,273],{"class":260},[255,318,276],{"class":260},[255,320,279],{"class":260},[255,322,323],{"class":282},"prj_01HXM...",[255,325,273],{"class":260},[255,327,288],{"class":260},[255,329,330,332,335,337,339,341,344,346],{"class":257,"line":46},[255,331,266],{"class":260},[255,333,334],{"class":269},"broadcast_id",[255,336,273],{"class":260},[255,338,276],{"class":260},[255,340,279],{"class":260},[255,342,343],{"class":282},"bdc_01HXM...",[255,345,273],{"class":260},[255,347,288],{"class":260},[255,349,350,352,355,357,359,361,364,366],{"class":257,"line":53},[255,351,266],{"class":260},[255,353,354],{"class":269},"subscriber_id",[255,356,273],{"class":260},[255,358,276],{"class":260},[255,360,279],{"class":260},[255,362,363],{"class":282},"sub_01HXM...",[255,365,273],{"class":260},[255,367,288],{"class":260},[255,369,370,372,375,377,379,381,384,386],{"class":257,"line":57},[255,371,266],{"class":260},[255,373,374],{"class":269},"external_id",[255,376,273],{"class":260},[255,378,276],{"class":260},[255,380,279],{"class":260},[255,382,383],{"class":282},"user_42",[255,385,273],{"class":260},[255,387,288],{"class":260},[255,389,390,392,395,397,399],{"class":257,"line":61},[255,391,266],{"class":260},[255,393,394],{"class":269},"meta",[255,396,273],{"class":260},[255,398,276],{"class":260},[255,400,401],{"class":260}," null,\n",[255,403,404,406,409,411,413],{"class":257,"line":65},[255,405,266],{"class":260},[255,407,408],{"class":269},"created_at",[255,410,273],{"class":260},[255,412,276],{"class":260},[255,414,416],{"class":415},"sbssI"," 1716762345123\n",[255,418,419],{"class":257,"line":69},[255,420,421],{"class":260},"}\n",[80,423,424,426,427,430,431,433,434,436,437,117,439,117,441,443,444,446,447,450],{},[104,425,374],{}," is whatever you passed at subscribe time, or ",[104,428,429],{},"null",". ",[104,432,394],{}," is ",[104,435,429],{}," on success-style events (",[104,438,201],{},[104,440,211],{},[104,442,227],{},"). On ",[104,445,237],{}," events it carries delivery diagnostics with one of three ",[104,448,449],{},"reason"," values:",[452,453,454],"blockquote",{},[80,455,456,465,466,468,469,471,472,468,475,478,479,481,482,468,484,486,487,489,490,464],{},[84,457,458,459,461,462,464],{},"Attribution caveat for ",[104,460,211],{}," \u002F ",[104,463,227],{},"."," These two events are reported by the service worker, which only knows the broadcast — not which subscriber it's running for. So ",[104,467,211],{}," and ",[104,470,227],{}," payloads always carry ",[104,473,474],{},"subscriber_id: null",[104,476,477],{},"external_id: null","; correlate them by ",[104,480,334],{},". Only ",[104,483,201],{},[104,485,237],{}," (emitted server-side during fan-out) carry the full ",[104,488,354],{}," + ",[104,491,374],{},[176,493,494,505],{},[179,495,496],{},[182,497,498,502],{},[185,499,500],{},[104,501,449],{},[185,503,504],{},"Meaning",[192,506,507,521,531],{},[182,508,509,514],{},[197,510,511],{},[104,512,513],{},"gone",[197,515,516,517,520],{},"The push gateway returned 404\u002F410 — this subscriber's subscription is permanently dead. The subscriber row is auto-flipped to ",[104,518,519],{},"unsubscribed"," on our side. Customers usually delete or flag the corresponding user in their DB.",[182,522,523,528],{},[197,524,525],{},[104,526,527],{},"transient_exhausted",[197,529,530],{},"The push gateway returned 5xx \u002F 429 \u002F network error, and our bounded inline retries also failed. The customer's subscription is still considered active — the next broadcast will retry from scratch. Treat as a soft failure; common during gateway hiccups.",[182,532,533,538],{},[197,534,535],{},[104,536,537],{},"error",[197,539,540,541,489,544,546],{},"A non-retryable error (e.g. VAPID-mismatch 4xx). The subscription is still active but the push didn't go out. Investigate via ",[104,542,543],{},"statusCode",[104,545,537],{}," fields.",[89,548,550],{"id":549},"headers","Headers",[80,552,553],{},"Every POST carries:",[246,555,560],{"className":556,"code":558,"language":559},[557],"language-text","Content-Type:         application\u002Fjson\nUser-Agent:           LitePush-Webhook\u002F1\nLitePush-Signature:   t=1716762345123,v1=a3f9c2d1...\nLitePush-Event-Type:  delivered\nLitePush-Event-Id:    evt_01HXM...\n","text",[104,561,558],{"__ignoreMap":251},[80,563,564,565,117,568,571],{},"The two extra headers (",[104,566,567],{},"Event-Type",[104,569,570],{},"Event-Id",") are conveniences for log routing — the source of truth is the body.",[89,573,575],{"id":574},"signature-verification","Signature verification",[80,577,578,579,582],{},"The signature is ",[104,580,581],{},"HMAC-SHA256(timestamp + \".\" + body)"," using your project's signing secret, lowercase hex.",[584,585,587],"h3",{"id":586},"verification-typescript-node","Verification — TypeScript \u002F Node",[246,589,593],{"className":590,"code":591,"language":592,"meta":251,"style":251},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nconst SECRET = process.env.LITEPUSH_WEBHOOK_SECRET!;\nconst TOLERANCE_MS = 5 * 60_000;\n\nfunction verify(rawBody: string, header: string | null): boolean {\n  if (!header) return false;\n\n  \u002F\u002F Header format: \"t=\u003Cms>,v1=\u003Chex>\"\n  const parts = Object.fromEntries(\n    header.split(\",\").map((kv) => kv.split(\"=\") as [string, string])\n  );\n  const t = Number(parts.t);\n  const v1 = parts.v1;\n  if (!t || !v1) return false;\n\n  \u002F\u002F Reject replays older than 5 minutes.\n  if (Math.abs(Date.now() - t) > TOLERANCE_MS) return false;\n\n  const expected = createHmac(\"sha256\", SECRET)\n    .update(`${t}.${rawBody}`)\n    .digest(\"hex\");\n\n  \u002F\u002F Constant-time compare — NEVER use === here.\n  const a = Buffer.from(expected, \"hex\");\n  const b = Buffer.from(v1, \"hex\");\n  return a.length === b.length && timingSafeEqual(a, b);\n}\n","ts",[104,594,595,630,636,663,683,687,733,760,764,770,792,864,872,899,918,945,950,956,1005,1010,1039,1070,1091,1096,1102,1137,1169,1208],{"__ignoreMap":251},[255,596,597,601,604,608,611,614,617,620,622,625,627],{"class":257,"line":7},[255,598,600],{"class":599},"s7zQu","import",[255,602,603],{"class":260}," {",[255,605,607],{"class":606},"sTEyZ"," createHmac",[255,609,610],{"class":260},",",[255,612,613],{"class":606}," timingSafeEqual",[255,615,616],{"class":260}," }",[255,618,619],{"class":599}," from",[255,621,279],{"class":260},[255,623,624],{"class":282},"node:crypto",[255,626,273],{"class":260},[255,628,629],{"class":260},";\n",[255,631,632],{"class":257,"line":22},[255,633,635],{"emptyLinePlaceholder":634},true,"\n",[255,637,638,641,644,647,650,652,655,657,660],{"class":257,"line":32},[255,639,640],{"class":269},"const",[255,642,643],{"class":606}," SECRET ",[255,645,646],{"class":260},"=",[255,648,649],{"class":606}," process",[255,651,464],{"class":260},[255,653,654],{"class":606},"env",[255,656,464],{"class":260},[255,658,659],{"class":606},"LITEPUSH_WEBHOOK_SECRET",[255,661,662],{"class":260},"!;\n",[255,664,665,667,670,672,675,678,681],{"class":257,"line":39},[255,666,640],{"class":269},[255,668,669],{"class":606}," TOLERANCE_MS ",[255,671,646],{"class":260},[255,673,674],{"class":415}," 5",[255,676,677],{"class":260}," *",[255,679,680],{"class":415}," 60_000",[255,682,629],{"class":260},[255,684,685],{"class":257,"line":46},[255,686,635],{"emptyLinePlaceholder":634},[255,688,689,692,696,699,703,705,709,711,714,716,718,721,724,727,730],{"class":257,"line":53},[255,690,691],{"class":269},"function",[255,693,695],{"class":694},"s2Zo4"," verify",[255,697,698],{"class":260},"(",[255,700,702],{"class":701},"sHdIc","rawBody",[255,704,276],{"class":260},[255,706,708],{"class":707},"sBMFI"," string",[255,710,610],{"class":260},[255,712,713],{"class":701}," header",[255,715,276],{"class":260},[255,717,708],{"class":707},[255,719,720],{"class":260}," |",[255,722,723],{"class":707}," null",[255,725,726],{"class":260},"):",[255,728,729],{"class":707}," boolean",[255,731,732],{"class":260}," {\n",[255,734,735,738,742,745,748,751,754,758],{"class":257,"line":57},[255,736,737],{"class":599},"  if",[255,739,741],{"class":740},"swJcz"," (",[255,743,744],{"class":260},"!",[255,746,747],{"class":606},"header",[255,749,750],{"class":740},") ",[255,752,753],{"class":599},"return",[255,755,757],{"class":756},"sfNiH"," false",[255,759,629],{"class":260},[255,761,762],{"class":257,"line":61},[255,763,635],{"emptyLinePlaceholder":634},[255,765,766],{"class":257,"line":65},[255,767,769],{"class":768},"sHwdD","  \u002F\u002F Header format: \"t=\u003Cms>,v1=\u003Chex>\"\n",[255,771,772,775,778,781,784,786,789],{"class":257,"line":69},[255,773,774],{"class":269},"  const",[255,776,777],{"class":606}," parts",[255,779,780],{"class":260}," =",[255,782,783],{"class":606}," Object",[255,785,464],{"class":260},[255,787,788],{"class":694},"fromEntries",[255,790,791],{"class":740},"(\n",[255,793,795,798,800,803,805,807,809,811,814,816,819,821,823,826,828,831,834,836,838,840,842,844,846,848,851,854,857,859,861],{"class":257,"line":794},11,[255,796,797],{"class":606},"    header",[255,799,464],{"class":260},[255,801,802],{"class":694},"split",[255,804,698],{"class":740},[255,806,273],{"class":260},[255,808,610],{"class":282},[255,810,273],{"class":260},[255,812,813],{"class":740},")",[255,815,464],{"class":260},[255,817,818],{"class":694},"map",[255,820,698],{"class":740},[255,822,698],{"class":260},[255,824,825],{"class":701},"kv",[255,827,813],{"class":260},[255,829,830],{"class":269}," =>",[255,832,833],{"class":606}," kv",[255,835,464],{"class":260},[255,837,802],{"class":694},[255,839,698],{"class":740},[255,841,273],{"class":260},[255,843,646],{"class":282},[255,845,273],{"class":260},[255,847,750],{"class":740},[255,849,850],{"class":599},"as",[255,852,853],{"class":740}," [",[255,855,856],{"class":707},"string",[255,858,610],{"class":260},[255,860,708],{"class":707},[255,862,863],{"class":740},"])\n",[255,865,867,870],{"class":257,"line":866},12,[255,868,869],{"class":740},"  )",[255,871,629],{"class":260},[255,873,875,877,880,882,885,887,890,892,895,897],{"class":257,"line":874},13,[255,876,774],{"class":269},[255,878,879],{"class":606}," t",[255,881,780],{"class":260},[255,883,884],{"class":694}," Number",[255,886,698],{"class":740},[255,888,889],{"class":606},"parts",[255,891,464],{"class":260},[255,893,894],{"class":606},"t",[255,896,813],{"class":740},[255,898,629],{"class":260},[255,900,902,904,907,909,911,913,916],{"class":257,"line":901},14,[255,903,774],{"class":269},[255,905,906],{"class":606}," v1",[255,908,780],{"class":260},[255,910,777],{"class":606},[255,912,464],{"class":260},[255,914,915],{"class":606},"v1",[255,917,629],{"class":260},[255,919,921,923,925,927,929,932,935,937,939,941,943],{"class":257,"line":920},15,[255,922,737],{"class":599},[255,924,741],{"class":740},[255,926,744],{"class":260},[255,928,894],{"class":606},[255,930,931],{"class":260}," ||",[255,933,934],{"class":260}," !",[255,936,915],{"class":606},[255,938,750],{"class":740},[255,940,753],{"class":599},[255,942,757],{"class":756},[255,944,629],{"class":260},[255,946,948],{"class":257,"line":947},16,[255,949,635],{"emptyLinePlaceholder":634},[255,951,953],{"class":257,"line":952},17,[255,954,955],{"class":768},"  \u002F\u002F Reject replays older than 5 minutes.\n",[255,957,959,961,963,966,968,971,973,976,978,981,984,987,989,991,994,997,999,1001,1003],{"class":257,"line":958},18,[255,960,737],{"class":599},[255,962,741],{"class":740},[255,964,965],{"class":606},"Math",[255,967,464],{"class":260},[255,969,970],{"class":694},"abs",[255,972,698],{"class":740},[255,974,975],{"class":606},"Date",[255,977,464],{"class":260},[255,979,980],{"class":694},"now",[255,982,983],{"class":740},"() ",[255,985,986],{"class":260},"-",[255,988,879],{"class":606},[255,990,750],{"class":740},[255,992,993],{"class":260},">",[255,995,996],{"class":606}," TOLERANCE_MS",[255,998,750],{"class":740},[255,1000,753],{"class":599},[255,1002,757],{"class":756},[255,1004,629],{"class":260},[255,1006,1008],{"class":257,"line":1007},19,[255,1009,635],{"emptyLinePlaceholder":634},[255,1011,1013,1015,1018,1020,1022,1024,1026,1029,1031,1033,1036],{"class":257,"line":1012},20,[255,1014,774],{"class":269},[255,1016,1017],{"class":606}," expected",[255,1019,780],{"class":260},[255,1021,607],{"class":694},[255,1023,698],{"class":740},[255,1025,273],{"class":260},[255,1027,1028],{"class":282},"sha256",[255,1030,273],{"class":260},[255,1032,610],{"class":260},[255,1034,1035],{"class":606}," SECRET",[255,1037,1038],{"class":740},")\n",[255,1040,1042,1045,1048,1050,1053,1055,1058,1060,1063,1065,1068],{"class":257,"line":1041},21,[255,1043,1044],{"class":260},"    .",[255,1046,1047],{"class":694},"update",[255,1049,698],{"class":740},[255,1051,1052],{"class":260},"`${",[255,1054,894],{"class":606},[255,1056,1057],{"class":260},"}",[255,1059,464],{"class":282},[255,1061,1062],{"class":260},"${",[255,1064,702],{"class":606},[255,1066,1067],{"class":260},"}`",[255,1069,1038],{"class":740},[255,1071,1073,1075,1078,1080,1082,1085,1087,1089],{"class":257,"line":1072},22,[255,1074,1044],{"class":260},[255,1076,1077],{"class":694},"digest",[255,1079,698],{"class":740},[255,1081,273],{"class":260},[255,1083,1084],{"class":282},"hex",[255,1086,273],{"class":260},[255,1088,813],{"class":740},[255,1090,629],{"class":260},[255,1092,1094],{"class":257,"line":1093},23,[255,1095,635],{"emptyLinePlaceholder":634},[255,1097,1099],{"class":257,"line":1098},24,[255,1100,1101],{"class":768},"  \u002F\u002F Constant-time compare — NEVER use === here.\n",[255,1103,1105,1107,1110,1112,1115,1117,1120,1122,1125,1127,1129,1131,1133,1135],{"class":257,"line":1104},25,[255,1106,774],{"class":269},[255,1108,1109],{"class":606}," a",[255,1111,780],{"class":260},[255,1113,1114],{"class":606}," Buffer",[255,1116,464],{"class":260},[255,1118,1119],{"class":694},"from",[255,1121,698],{"class":740},[255,1123,1124],{"class":606},"expected",[255,1126,610],{"class":260},[255,1128,279],{"class":260},[255,1130,1084],{"class":282},[255,1132,273],{"class":260},[255,1134,813],{"class":740},[255,1136,629],{"class":260},[255,1138,1140,1142,1145,1147,1149,1151,1153,1155,1157,1159,1161,1163,1165,1167],{"class":257,"line":1139},26,[255,1141,774],{"class":269},[255,1143,1144],{"class":606}," b",[255,1146,780],{"class":260},[255,1148,1114],{"class":606},[255,1150,464],{"class":260},[255,1152,1119],{"class":694},[255,1154,698],{"class":740},[255,1156,915],{"class":606},[255,1158,610],{"class":260},[255,1160,279],{"class":260},[255,1162,1084],{"class":282},[255,1164,273],{"class":260},[255,1166,813],{"class":740},[255,1168,629],{"class":260},[255,1170,1172,1175,1177,1179,1182,1185,1187,1189,1191,1194,1196,1198,1200,1202,1204,1206],{"class":257,"line":1171},27,[255,1173,1174],{"class":599},"  return",[255,1176,1109],{"class":606},[255,1178,464],{"class":260},[255,1180,1181],{"class":606},"length",[255,1183,1184],{"class":260}," ===",[255,1186,1144],{"class":606},[255,1188,464],{"class":260},[255,1190,1181],{"class":606},[255,1192,1193],{"class":260}," &&",[255,1195,613],{"class":694},[255,1197,698],{"class":740},[255,1199,216],{"class":606},[255,1201,610],{"class":260},[255,1203,1144],{"class":606},[255,1205,813],{"class":740},[255,1207,629],{"class":260},[255,1209,1211],{"class":257,"line":1210},28,[255,1212,421],{"class":260},[584,1214,1216],{"id":1215},"verification-cloudflare-workers-web-crypto","Verification — Cloudflare Workers \u002F Web Crypto",[80,1218,1219,1220,276],{},"If you're on Cloudflare Workers or another edge runtime without ",[104,1221,624],{},[246,1223,1225],{"className":590,"code":1224,"language":592,"meta":251,"style":251},"async function verify(rawBody: string, header: string | null, secret: string) {\n  if (!header) return false;\n  const parts = Object.fromEntries(\n    header.split(\",\").map((kv) => kv.split(\"=\") as [string, string])\n  );\n  const t = Number(parts.t);\n  const v1 = parts.v1;\n  if (!t || !v1) return false;\n  if (Math.abs(Date.now() - t) > 5 * 60_000) return false;\n\n  const key = await crypto.subtle.importKey(\n    \"raw\",\n    new TextEncoder().encode(secret),\n    { name: \"HMAC\", hash: \"SHA-256\" },\n    false,\n    [\"sign\"],\n  );\n  const sigBuf = await crypto.subtle.sign(\n    \"HMAC\",\n    key,\n    new TextEncoder().encode(`${t}.${rawBody}`),\n  );\n  const expected = [...new Uint8Array(sigBuf)]\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n\n  if (expected.length !== v1.length) return false;\n  let diff = 0;\n  for (let i = 0; i \u003C expected.length; i++) {\n    diff |= expected.charCodeAt(i) ^ v1.charCodeAt(i);\n  }\n  return diff === 0;\n}\n",[104,1226,1227,1270,1288,1304,1364,1370,1392,1408,1432,1476,1480,1507,1519,1544,1578,1585,1602,1608,1631,1641,1648,1680,1686,1710,1763,1779,1783,1812,1827,1870,1910,1916,1929],{"__ignoreMap":251},[255,1228,1229,1232,1235,1237,1239,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259,1262,1264,1266,1268],{"class":257,"line":7},[255,1230,1231],{"class":269},"async",[255,1233,1234],{"class":269}," function",[255,1236,695],{"class":694},[255,1238,698],{"class":260},[255,1240,702],{"class":701},[255,1242,276],{"class":260},[255,1244,708],{"class":707},[255,1246,610],{"class":260},[255,1248,713],{"class":701},[255,1250,276],{"class":260},[255,1252,708],{"class":707},[255,1254,720],{"class":260},[255,1256,723],{"class":707},[255,1258,610],{"class":260},[255,1260,1261],{"class":701}," secret",[255,1263,276],{"class":260},[255,1265,708],{"class":707},[255,1267,813],{"class":260},[255,1269,732],{"class":260},[255,1271,1272,1274,1276,1278,1280,1282,1284,1286],{"class":257,"line":22},[255,1273,737],{"class":599},[255,1275,741],{"class":740},[255,1277,744],{"class":260},[255,1279,747],{"class":606},[255,1281,750],{"class":740},[255,1283,753],{"class":599},[255,1285,757],{"class":756},[255,1287,629],{"class":260},[255,1289,1290,1292,1294,1296,1298,1300,1302],{"class":257,"line":32},[255,1291,774],{"class":269},[255,1293,777],{"class":606},[255,1295,780],{"class":260},[255,1297,783],{"class":606},[255,1299,464],{"class":260},[255,1301,788],{"class":694},[255,1303,791],{"class":740},[255,1305,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1326,1328,1330,1332,1334,1336,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360,1362],{"class":257,"line":39},[255,1307,797],{"class":606},[255,1309,464],{"class":260},[255,1311,802],{"class":694},[255,1313,698],{"class":740},[255,1315,273],{"class":260},[255,1317,610],{"class":282},[255,1319,273],{"class":260},[255,1321,813],{"class":740},[255,1323,464],{"class":260},[255,1325,818],{"class":694},[255,1327,698],{"class":740},[255,1329,698],{"class":260},[255,1331,825],{"class":701},[255,1333,813],{"class":260},[255,1335,830],{"class":269},[255,1337,833],{"class":606},[255,1339,464],{"class":260},[255,1341,802],{"class":694},[255,1343,698],{"class":740},[255,1345,273],{"class":260},[255,1347,646],{"class":282},[255,1349,273],{"class":260},[255,1351,750],{"class":740},[255,1353,850],{"class":599},[255,1355,853],{"class":740},[255,1357,856],{"class":707},[255,1359,610],{"class":260},[255,1361,708],{"class":707},[255,1363,863],{"class":740},[255,1365,1366,1368],{"class":257,"line":46},[255,1367,869],{"class":740},[255,1369,629],{"class":260},[255,1371,1372,1374,1376,1378,1380,1382,1384,1386,1388,1390],{"class":257,"line":53},[255,1373,774],{"class":269},[255,1375,879],{"class":606},[255,1377,780],{"class":260},[255,1379,884],{"class":694},[255,1381,698],{"class":740},[255,1383,889],{"class":606},[255,1385,464],{"class":260},[255,1387,894],{"class":606},[255,1389,813],{"class":740},[255,1391,629],{"class":260},[255,1393,1394,1396,1398,1400,1402,1404,1406],{"class":257,"line":57},[255,1395,774],{"class":269},[255,1397,906],{"class":606},[255,1399,780],{"class":260},[255,1401,777],{"class":606},[255,1403,464],{"class":260},[255,1405,915],{"class":606},[255,1407,629],{"class":260},[255,1409,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428,1430],{"class":257,"line":61},[255,1411,737],{"class":599},[255,1413,741],{"class":740},[255,1415,744],{"class":260},[255,1417,894],{"class":606},[255,1419,931],{"class":260},[255,1421,934],{"class":260},[255,1423,915],{"class":606},[255,1425,750],{"class":740},[255,1427,753],{"class":599},[255,1429,757],{"class":756},[255,1431,629],{"class":260},[255,1433,1434,1436,1438,1440,1442,1444,1446,1448,1450,1452,1454,1456,1458,1460,1462,1464,1466,1468,1470,1472,1474],{"class":257,"line":65},[255,1435,737],{"class":599},[255,1437,741],{"class":740},[255,1439,965],{"class":606},[255,1441,464],{"class":260},[255,1443,970],{"class":694},[255,1445,698],{"class":740},[255,1447,975],{"class":606},[255,1449,464],{"class":260},[255,1451,980],{"class":694},[255,1453,983],{"class":740},[255,1455,986],{"class":260},[255,1457,879],{"class":606},[255,1459,750],{"class":740},[255,1461,993],{"class":260},[255,1463,674],{"class":415},[255,1465,677],{"class":260},[255,1467,680],{"class":415},[255,1469,750],{"class":740},[255,1471,753],{"class":599},[255,1473,757],{"class":756},[255,1475,629],{"class":260},[255,1477,1478],{"class":257,"line":69},[255,1479,635],{"emptyLinePlaceholder":634},[255,1481,1482,1484,1487,1489,1492,1495,1497,1500,1502,1505],{"class":257,"line":794},[255,1483,774],{"class":269},[255,1485,1486],{"class":606}," key",[255,1488,780],{"class":260},[255,1490,1491],{"class":599}," await",[255,1493,1494],{"class":606}," crypto",[255,1496,464],{"class":260},[255,1498,1499],{"class":606},"subtle",[255,1501,464],{"class":260},[255,1503,1504],{"class":694},"importKey",[255,1506,791],{"class":740},[255,1508,1509,1512,1515,1517],{"class":257,"line":866},[255,1510,1511],{"class":260},"    \"",[255,1513,1514],{"class":282},"raw",[255,1516,273],{"class":260},[255,1518,288],{"class":260},[255,1520,1521,1524,1527,1530,1532,1535,1537,1540,1542],{"class":257,"line":874},[255,1522,1523],{"class":260},"    new",[255,1525,1526],{"class":694}," TextEncoder",[255,1528,1529],{"class":740},"()",[255,1531,464],{"class":260},[255,1533,1534],{"class":694},"encode",[255,1536,698],{"class":740},[255,1538,1539],{"class":606},"secret",[255,1541,813],{"class":740},[255,1543,288],{"class":260},[255,1545,1546,1549,1552,1554,1556,1559,1561,1563,1566,1568,1570,1573,1575],{"class":257,"line":901},[255,1547,1548],{"class":260},"    {",[255,1550,1551],{"class":740}," name",[255,1553,276],{"class":260},[255,1555,279],{"class":260},[255,1557,1558],{"class":282},"HMAC",[255,1560,273],{"class":260},[255,1562,610],{"class":260},[255,1564,1565],{"class":740}," hash",[255,1567,276],{"class":260},[255,1569,279],{"class":260},[255,1571,1572],{"class":282},"SHA-256",[255,1574,273],{"class":260},[255,1576,1577],{"class":260}," },\n",[255,1579,1580,1583],{"class":257,"line":920},[255,1581,1582],{"class":756},"    false",[255,1584,288],{"class":260},[255,1586,1587,1590,1592,1595,1597,1600],{"class":257,"line":947},[255,1588,1589],{"class":740},"    [",[255,1591,273],{"class":260},[255,1593,1594],{"class":282},"sign",[255,1596,273],{"class":260},[255,1598,1599],{"class":740},"]",[255,1601,288],{"class":260},[255,1603,1604,1606],{"class":257,"line":952},[255,1605,869],{"class":740},[255,1607,629],{"class":260},[255,1609,1610,1612,1615,1617,1619,1621,1623,1625,1627,1629],{"class":257,"line":958},[255,1611,774],{"class":269},[255,1613,1614],{"class":606}," sigBuf",[255,1616,780],{"class":260},[255,1618,1491],{"class":599},[255,1620,1494],{"class":606},[255,1622,464],{"class":260},[255,1624,1499],{"class":606},[255,1626,464],{"class":260},[255,1628,1594],{"class":694},[255,1630,791],{"class":740},[255,1632,1633,1635,1637,1639],{"class":257,"line":1007},[255,1634,1511],{"class":260},[255,1636,1558],{"class":282},[255,1638,273],{"class":260},[255,1640,288],{"class":260},[255,1642,1643,1646],{"class":257,"line":1012},[255,1644,1645],{"class":606},"    key",[255,1647,288],{"class":260},[255,1649,1650,1652,1654,1656,1658,1660,1662,1664,1666,1668,1670,1672,1674,1676,1678],{"class":257,"line":1041},[255,1651,1523],{"class":260},[255,1653,1526],{"class":694},[255,1655,1529],{"class":740},[255,1657,464],{"class":260},[255,1659,1534],{"class":694},[255,1661,698],{"class":740},[255,1663,1052],{"class":260},[255,1665,894],{"class":606},[255,1667,1057],{"class":260},[255,1669,464],{"class":282},[255,1671,1062],{"class":260},[255,1673,702],{"class":606},[255,1675,1067],{"class":260},[255,1677,813],{"class":740},[255,1679,288],{"class":260},[255,1681,1682,1684],{"class":257,"line":1072},[255,1683,869],{"class":740},[255,1685,629],{"class":260},[255,1687,1688,1690,1692,1694,1696,1699,1702,1704,1707],{"class":257,"line":1093},[255,1689,774],{"class":269},[255,1691,1017],{"class":606},[255,1693,780],{"class":260},[255,1695,853],{"class":740},[255,1697,1698],{"class":260},"...new",[255,1700,1701],{"class":694}," Uint8Array",[255,1703,698],{"class":740},[255,1705,1706],{"class":606},"sigBuf",[255,1708,1709],{"class":740},")]\n",[255,1711,1712,1714,1716,1718,1720,1723,1725,1727,1729,1731,1734,1736,1739,1741,1743,1746,1748,1751,1753,1755,1758,1760],{"class":257,"line":1098},[255,1713,1044],{"class":260},[255,1715,818],{"class":694},[255,1717,698],{"class":740},[255,1719,698],{"class":260},[255,1721,1722],{"class":701},"b",[255,1724,813],{"class":260},[255,1726,830],{"class":269},[255,1728,1144],{"class":606},[255,1730,464],{"class":260},[255,1732,1733],{"class":694},"toString",[255,1735,698],{"class":740},[255,1737,1738],{"class":415},"16",[255,1740,813],{"class":740},[255,1742,464],{"class":260},[255,1744,1745],{"class":694},"padStart",[255,1747,698],{"class":740},[255,1749,1750],{"class":415},"2",[255,1752,610],{"class":260},[255,1754,279],{"class":260},[255,1756,1757],{"class":282},"0",[255,1759,273],{"class":260},[255,1761,1762],{"class":740},"))\n",[255,1764,1765,1767,1770,1772,1775,1777],{"class":257,"line":1104},[255,1766,1044],{"class":260},[255,1768,1769],{"class":694},"join",[255,1771,698],{"class":740},[255,1773,1774],{"class":260},"\"\"",[255,1776,813],{"class":740},[255,1778,629],{"class":260},[255,1780,1781],{"class":257,"line":1139},[255,1782,635],{"emptyLinePlaceholder":634},[255,1784,1785,1787,1789,1791,1793,1795,1798,1800,1802,1804,1806,1808,1810],{"class":257,"line":1171},[255,1786,737],{"class":599},[255,1788,741],{"class":740},[255,1790,1124],{"class":606},[255,1792,464],{"class":260},[255,1794,1181],{"class":606},[255,1796,1797],{"class":260}," !==",[255,1799,906],{"class":606},[255,1801,464],{"class":260},[255,1803,1181],{"class":606},[255,1805,750],{"class":740},[255,1807,753],{"class":599},[255,1809,757],{"class":756},[255,1811,629],{"class":260},[255,1813,1814,1817,1820,1822,1825],{"class":257,"line":1210},[255,1815,1816],{"class":269},"  let",[255,1818,1819],{"class":606}," diff",[255,1821,780],{"class":260},[255,1823,1824],{"class":415}," 0",[255,1826,629],{"class":260},[255,1828,1830,1833,1835,1838,1841,1843,1845,1848,1850,1853,1855,1857,1859,1861,1863,1866,1868],{"class":257,"line":1829},29,[255,1831,1832],{"class":599},"  for",[255,1834,741],{"class":740},[255,1836,1837],{"class":269},"let",[255,1839,1840],{"class":606}," i",[255,1842,780],{"class":260},[255,1844,1824],{"class":415},[255,1846,1847],{"class":260},";",[255,1849,1840],{"class":606},[255,1851,1852],{"class":260}," \u003C",[255,1854,1017],{"class":606},[255,1856,464],{"class":260},[255,1858,1181],{"class":606},[255,1860,1847],{"class":260},[255,1862,1840],{"class":606},[255,1864,1865],{"class":260},"++",[255,1867,750],{"class":740},[255,1869,261],{"class":260},[255,1871,1873,1876,1879,1881,1883,1886,1888,1891,1893,1896,1898,1900,1902,1904,1906,1908],{"class":257,"line":1872},30,[255,1874,1875],{"class":606},"    diff",[255,1877,1878],{"class":260}," |=",[255,1880,1017],{"class":606},[255,1882,464],{"class":260},[255,1884,1885],{"class":694},"charCodeAt",[255,1887,698],{"class":740},[255,1889,1890],{"class":606},"i",[255,1892,750],{"class":740},[255,1894,1895],{"class":260},"^",[255,1897,906],{"class":606},[255,1899,464],{"class":260},[255,1901,1885],{"class":694},[255,1903,698],{"class":740},[255,1905,1890],{"class":606},[255,1907,813],{"class":740},[255,1909,629],{"class":260},[255,1911,1913],{"class":257,"line":1912},31,[255,1914,1915],{"class":260},"  }\n",[255,1917,1919,1921,1923,1925,1927],{"class":257,"line":1918},32,[255,1920,1174],{"class":599},[255,1922,1819],{"class":606},[255,1924,1184],{"class":260},[255,1926,1824],{"class":415},[255,1928,629],{"class":260},[255,1930,1932],{"class":257,"line":1931},33,[255,1933,421],{"class":260},[89,1935,1937],{"id":1936},"handler-best-practices","Handler best practices",[246,1939,1941],{"className":590,"code":1940,"language":592,"meta":251,"style":251},"\u002F\u002F Hono on Cloudflare Workers\napp.post(\"\u002Fwebhooks\u002Flitepush\", async (c) => {\n  \u002F\u002F CRITICAL: read the raw body, not parsed JSON. The signature was\n  \u002F\u002F computed over the exact bytes we sent — parsing then re-serialising\n  \u002F\u002F changes whitespace and breaks the HMAC.\n  const rawBody = await c.req.text();\n  const sigHeader = c.req.header(\"LitePush-Signature\");\n\n  if (!(await verify(rawBody, sigHeader, c.env.LITEPUSH_WEBHOOK_SECRET))) {\n    return c.json({ error: \"invalid signature\" }, 401);\n  }\n\n  const event = JSON.parse(rawBody);\n\n  \u002F\u002F Idempotency: retries deliver the same event.id with a NEW signature\n  \u002F\u002F timestamp. Dedupe by event.id on your side.\n  if (await alreadyProcessed(event.id)) {\n    return c.json({ ok: true }); \u002F\u002F ack so we stop retrying\n  }\n  await markProcessed(event.id);\n\n  \u002F\u002F ... your business logic ...\n\n  \u002F\u002F Return 200 fast — heavy work should be enqueued, not awaited inline.\n  return c.json({ ok: true });\n});\n",[104,1942,1943,1948,1983,1988,1993,1998,2025,2057,2061,2101,2139,2143,2147,2172,2176,2181,2186,2211,2242,2246,2266,2270,2275,2279,2284,2310],{"__ignoreMap":251},[255,1944,1945],{"class":257,"line":7},[255,1946,1947],{"class":768},"\u002F\u002F Hono on Cloudflare Workers\n",[255,1949,1950,1953,1955,1958,1960,1962,1965,1967,1969,1972,1974,1977,1979,1981],{"class":257,"line":22},[255,1951,1952],{"class":606},"app",[255,1954,464],{"class":260},[255,1956,1957],{"class":694},"post",[255,1959,698],{"class":606},[255,1961,273],{"class":260},[255,1963,1964],{"class":282},"\u002Fwebhooks\u002Flitepush",[255,1966,273],{"class":260},[255,1968,610],{"class":260},[255,1970,1971],{"class":269}," async",[255,1973,741],{"class":260},[255,1975,1976],{"class":701},"c",[255,1978,813],{"class":260},[255,1980,830],{"class":269},[255,1982,732],{"class":260},[255,1984,1985],{"class":257,"line":32},[255,1986,1987],{"class":768},"  \u002F\u002F CRITICAL: read the raw body, not parsed JSON. The signature was\n",[255,1989,1990],{"class":257,"line":39},[255,1991,1992],{"class":768},"  \u002F\u002F computed over the exact bytes we sent — parsing then re-serialising\n",[255,1994,1995],{"class":257,"line":46},[255,1996,1997],{"class":768},"  \u002F\u002F changes whitespace and breaks the HMAC.\n",[255,1999,2000,2002,2005,2007,2009,2012,2014,2017,2019,2021,2023],{"class":257,"line":53},[255,2001,774],{"class":269},[255,2003,2004],{"class":606}," rawBody",[255,2006,780],{"class":260},[255,2008,1491],{"class":599},[255,2010,2011],{"class":606}," c",[255,2013,464],{"class":260},[255,2015,2016],{"class":606},"req",[255,2018,464],{"class":260},[255,2020,559],{"class":694},[255,2022,1529],{"class":740},[255,2024,629],{"class":260},[255,2026,2027,2029,2032,2034,2036,2038,2040,2042,2044,2046,2048,2051,2053,2055],{"class":257,"line":57},[255,2028,774],{"class":269},[255,2030,2031],{"class":606}," sigHeader",[255,2033,780],{"class":260},[255,2035,2011],{"class":606},[255,2037,464],{"class":260},[255,2039,2016],{"class":606},[255,2041,464],{"class":260},[255,2043,747],{"class":694},[255,2045,698],{"class":740},[255,2047,273],{"class":260},[255,2049,2050],{"class":282},"LitePush-Signature",[255,2052,273],{"class":260},[255,2054,813],{"class":740},[255,2056,629],{"class":260},[255,2058,2059],{"class":257,"line":61},[255,2060,635],{"emptyLinePlaceholder":634},[255,2062,2063,2065,2067,2069,2071,2074,2076,2078,2080,2082,2084,2086,2088,2090,2092,2094,2096,2099],{"class":257,"line":65},[255,2064,737],{"class":599},[255,2066,741],{"class":740},[255,2068,744],{"class":260},[255,2070,698],{"class":740},[255,2072,2073],{"class":599},"await",[255,2075,695],{"class":694},[255,2077,698],{"class":740},[255,2079,702],{"class":606},[255,2081,610],{"class":260},[255,2083,2031],{"class":606},[255,2085,610],{"class":260},[255,2087,2011],{"class":606},[255,2089,464],{"class":260},[255,2091,654],{"class":606},[255,2093,464],{"class":260},[255,2095,659],{"class":606},[255,2097,2098],{"class":740},"))) ",[255,2100,261],{"class":260},[255,2102,2103,2106,2108,2110,2112,2114,2117,2120,2122,2124,2127,2129,2132,2135,2137],{"class":257,"line":69},[255,2104,2105],{"class":599},"    return",[255,2107,2011],{"class":606},[255,2109,464],{"class":260},[255,2111,250],{"class":694},[255,2113,698],{"class":740},[255,2115,2116],{"class":260},"{",[255,2118,2119],{"class":740}," error",[255,2121,276],{"class":260},[255,2123,279],{"class":260},[255,2125,2126],{"class":282},"invalid signature",[255,2128,273],{"class":260},[255,2130,2131],{"class":260}," },",[255,2133,2134],{"class":415}," 401",[255,2136,813],{"class":740},[255,2138,629],{"class":260},[255,2140,2141],{"class":257,"line":794},[255,2142,1915],{"class":260},[255,2144,2145],{"class":257,"line":866},[255,2146,635],{"emptyLinePlaceholder":634},[255,2148,2149,2151,2154,2156,2159,2161,2164,2166,2168,2170],{"class":257,"line":874},[255,2150,774],{"class":269},[255,2152,2153],{"class":606}," event",[255,2155,780],{"class":260},[255,2157,2158],{"class":606}," JSON",[255,2160,464],{"class":260},[255,2162,2163],{"class":694},"parse",[255,2165,698],{"class":740},[255,2167,702],{"class":606},[255,2169,813],{"class":740},[255,2171,629],{"class":260},[255,2173,2174],{"class":257,"line":901},[255,2175,635],{"emptyLinePlaceholder":634},[255,2177,2178],{"class":257,"line":920},[255,2179,2180],{"class":768},"  \u002F\u002F Idempotency: retries deliver the same event.id with a NEW signature\n",[255,2182,2183],{"class":257,"line":947},[255,2184,2185],{"class":768},"  \u002F\u002F timestamp. Dedupe by event.id on your side.\n",[255,2187,2188,2190,2192,2194,2197,2199,2202,2204,2206,2209],{"class":257,"line":952},[255,2189,737],{"class":599},[255,2191,741],{"class":740},[255,2193,2073],{"class":599},[255,2195,2196],{"class":694}," alreadyProcessed",[255,2198,698],{"class":740},[255,2200,2201],{"class":606},"event",[255,2203,464],{"class":260},[255,2205,270],{"class":606},[255,2207,2208],{"class":740},")) ",[255,2210,261],{"class":260},[255,2212,2213,2215,2217,2219,2221,2223,2225,2228,2230,2233,2235,2237,2239],{"class":257,"line":958},[255,2214,2105],{"class":599},[255,2216,2011],{"class":606},[255,2218,464],{"class":260},[255,2220,250],{"class":694},[255,2222,698],{"class":740},[255,2224,2116],{"class":260},[255,2226,2227],{"class":740}," ok",[255,2229,276],{"class":260},[255,2231,2232],{"class":756}," true",[255,2234,616],{"class":260},[255,2236,813],{"class":740},[255,2238,1847],{"class":260},[255,2240,2241],{"class":768}," \u002F\u002F ack so we stop retrying\n",[255,2243,2244],{"class":257,"line":1007},[255,2245,1915],{"class":260},[255,2247,2248,2251,2254,2256,2258,2260,2262,2264],{"class":257,"line":1012},[255,2249,2250],{"class":599},"  await",[255,2252,2253],{"class":694}," markProcessed",[255,2255,698],{"class":740},[255,2257,2201],{"class":606},[255,2259,464],{"class":260},[255,2261,270],{"class":606},[255,2263,813],{"class":740},[255,2265,629],{"class":260},[255,2267,2268],{"class":257,"line":1041},[255,2269,635],{"emptyLinePlaceholder":634},[255,2271,2272],{"class":257,"line":1072},[255,2273,2274],{"class":768},"  \u002F\u002F ... your business logic ...\n",[255,2276,2277],{"class":257,"line":1093},[255,2278,635],{"emptyLinePlaceholder":634},[255,2280,2281],{"class":257,"line":1098},[255,2282,2283],{"class":768},"  \u002F\u002F Return 200 fast — heavy work should be enqueued, not awaited inline.\n",[255,2285,2286,2288,2290,2292,2294,2296,2298,2300,2302,2304,2306,2308],{"class":257,"line":1104},[255,2287,1174],{"class":599},[255,2289,2011],{"class":606},[255,2291,464],{"class":260},[255,2293,250],{"class":694},[255,2295,698],{"class":740},[255,2297,2116],{"class":260},[255,2299,2227],{"class":740},[255,2301,276],{"class":260},[255,2303,2232],{"class":756},[255,2305,616],{"class":260},[255,2307,813],{"class":740},[255,2309,629],{"class":260},[255,2311,2312,2314,2316],{"class":257,"line":1139},[255,2313,1057],{"class":260},[255,2315,813],{"class":606},[255,2317,629],{"class":260},[89,2319,2321],{"id":2320},"retries","Retries",[80,2323,2324,2325,2328],{},"Non-2xx responses (or timeouts past 10s) get retried up to ",[84,2326,2327],{},"5 times"," with exponential backoff. After 5 attempts the message is dropped — we don't queue indefinitely.",[80,2330,2331],{},"If your endpoint is down for hours, you'll lose any events that fired during the outage. Plan accordingly — for high-stakes signals consider also polling the dashboard's broadcast detail endpoint.",[89,2333,2335],{"id":2334},"rotating-the-signing-secret","Rotating the signing secret",[80,2337,2338,2341,2342,2345],{},[84,2339,2340],{},"Project → Settings → Webhooks → Rotate signing secret."," Generates a fresh ",[104,2343,2344],{},"whsec_*"," and invalidates the old one immediately. In-flight queue messages (a few seconds) still carry the old secret, so brief overlap is expected — rotate during a low-traffic window.",[2347,2348,2349],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":251,"searchDepth":22,"depth":22,"links":2351},[2352,2353,2354,2355,2356,2360,2361,2362],{"id":91,"depth":22,"text":92},{"id":170,"depth":22,"text":171},{"id":243,"depth":22,"text":244},{"id":549,"depth":22,"text":550},{"id":574,"depth":22,"text":575,"children":2357},[2358,2359],{"id":586,"depth":32,"text":587},{"id":1215,"depth":32,"text":1216},{"id":1936,"depth":22,"text":1937},{"id":2320,"depth":22,"text":2321},{"id":2334,"depth":22,"text":2335},"Real-time event stream from LitePush to your server. HMAC-signed, retried with backoff.","md",false,{},{"title":67,"description":2363},"docs\u002Fapi\u002Fwebhooks","olKiCsm87uycrwoRg4-TZ55c_4Xmj1EouCZT_iBmZrI",1780560203630]