[{"data":1,"prerenderedAt":1021},["ShallowReactive",2],{"docs-nav":3,"content:\u002Fguides\u002Fwebhooks":78},[4,18,29,35,46,63,66,69,72,75],{"path":5,"title":6,"navTitle":6,"order":7,"subnav":8},"\u002Fapi\u002Fapi-tokens","API tokens",3,[9,12,15],{"title":10,"anchor":11},"Create an API key","create-an-api-key",{"title":13,"anchor":14},"List API keys","list-api-keys",{"title":16,"anchor":17},"Revoke an API key","revoke-an-api-key",{"path":19,"title":20,"navTitle":20,"order":21,"subnav":22},"\u002Fapi\u002Fbalances","Balances",4,[23,26],{"title":24,"anchor":25},"The balance object","the-balance-object",{"title":27,"anchor":28},"List balances","list-balances",{"path":30,"title":31,"navTitle":32,"order":33,"subnav":34},"\u002Fapi","API overview","Overview",1,null,{"path":36,"title":37,"navTitle":37,"order":38,"subnav":39},"\u002Fapi\u002Fsender-ids","Sender IDs",5,[40,43],{"title":41,"anchor":42},"The sender identity object","the-sender-identity-object",{"title":44,"anchor":45},"List sender IDs","list-sender-ids",{"path":47,"title":48,"navTitle":48,"order":49,"subnav":50},"\u002Fapi\u002Fsms","SMS",2,[51,54,57,60],{"title":52,"anchor":53},"The message object","the-message-object",{"title":55,"anchor":56},"Send an SMS","send-an-sms",{"title":58,"anchor":59},"Retrieve an SMS","retrieve-an-sms",{"title":61,"anchor":62},"Send bulk SMS","send-bulk-sms",{"path":64,"title":65,"navTitle":65,"order":49,"subnav":34},"\u002Fguides\u002Fauthentication","Authentication",{"path":67,"title":68,"navTitle":68,"order":7,"subnav":34},"\u002Fguides\u002Fbulk-sms","Bulk SMS",{"path":70,"title":71,"navTitle":71,"order":38,"subnav":34},"\u002Fguides\u002Fmcp","AI agents (MCP)",{"path":73,"title":74,"navTitle":74,"order":33,"subnav":34},"\u002Fguides\u002Fquickstart","Quickstart",{"path":76,"title":77,"navTitle":77,"order":21,"subnav":34},"\u002Fguides\u002Fwebhooks","Webhooks",{"id":79,"path":76,"title":77,"description":80,"navTitle":77,"order":21,"wide":81,"body":82,"seo":1017,"stem":1018,"extension":1019,"meta":1020,"navigation":323},"content\u002Fguides\u002Fwebhooks.md","Have Sendai call your endpoint when a message is delivered or fails — signed with HMAC-SHA256 so you can prove every delivery came from us.",false,{"type":83,"value":84,"toc":1006},"minimark",[85,99,104,107,153,164,168,175,193,201,205,220,231,240,244,247,274,866,876,880,886,893,897,903,923,927,962,966,980,984,1002],[86,87,88,89,93,94,98],"p",{},"Polling ",[90,91,92],"code",{},"GET \u002Fapi\u002Fv1\u002Fsms\u002F{id}"," works, but for anything beyond a handful of messages you want\nSendai to tell ",[95,96,97],"em",{},"you",". Register a webhook endpoint and Sendai POSTs signed JSON to your URL\nas events happen — each request carries an HMAC-SHA256 signature so you can verify it came\nfrom Sendai and not from anyone who knows your URL.",[100,101,103],"h2",{"id":102},"the-events","The events",[86,105,106],{},"An endpoint subscribes to one or more of four events:",[108,109,110,129,139,145],"properties",{},[111,112,115],"property",{"name":113,"type":114},"message.delivered","event",[86,116,117,118,121,122,128],{},"Fires when the carrier confirms a message reached the handset — the same fact as\n",[90,119,120],{},"delivered_at"," becoming non-null on ",[123,124,126],"a",{"href":125},"\u002Fapi\u002Fsms#retrieve-an-sms",[90,127,92],{},". One event per\nsuccessful delivery receipt, so a bulk send to 5,000 recipients produces up to 5,000 of\nthese.",[111,130,132],{"name":131,"type":114},"message.failed",[86,133,134,135,138],{},"Fires when a message fails — bounces and carrier failures. The push-side counterpart of a\nmessage ending in ",[90,136,137],{},"status: failed",".",[111,140,142],{"name":141,"type":114},"campaign.started",[86,143,144],{},"Fires when a campaign composed in the dashboard begins sending.",[111,146,148],{"name":147,"type":114},"campaign.completed",[86,149,150,151,138],{},"Fires when a campaign finishes sending — the bookend to ",[90,152,141],{},[86,154,155,156,159,160,163],{},"For per-recipient delivery tracking, subscribe to the two ",[90,157,158],{},"message.*"," events. The\n",[90,161,162],{},"campaign.*"," pair covers campaigns composed in the dashboard, and is useful when you care\nabout the campaign as a unit rather than each recipient.",[100,165,167],{"id":166},"what-a-delivery-looks-like","What a delivery looks like",[86,169,170,171,174],{},"Every delivery is an HTTPS ",[90,172,173],{},"POST"," of a JSON body to your endpoint, with one header that\nmatters:",[108,176,177],{},[111,178,181],{"name":179,"type":180},"X-Sendai-Signature","header",[86,182,183,184,188,189,192],{},"An ",[185,186,187],"strong",{},"HMAC-SHA256"," of the request body, keyed with your endpoint's signing secret (the\n",[90,190,191],{},"whsec_…"," value from registration). Verify it before trusting the payload — an unsigned or\nmis-signed request is not from Sendai.",[86,194,195,196,200],{},"The exact JSON body shape is not part of the documented contract yet, so don't build against\nguessed field names — capture a real body with a ",[123,197,199],{"href":198},"#test-deliveries","test delivery"," and treat\nthe event name and the message id it references as the parts to key your processing on.",[100,202,204],{"id":203},"register-an-endpoint","Register an endpoint",[86,206,207,208,211,212,215,216,219],{},"Register endpoints in the dashboard under ",[185,209,210],{},"Settings",": give it a URL and pick the events it\nshould receive. The URL must be ",[185,213,214],{},"HTTPS",", and the backend rejects unresolvable or private\nhosts — a webhook pointed at ",[90,217,218],{},"localhost"," will not register; use a tunnel while developing.",[86,221,222,223,226,227,230],{},"The create step responds with the endpoint's ",[185,224,225],{},"signing secret"," — a ",[90,228,229],{},"whsec_"," value.",[232,233,234],"blockquote",{},[86,235,236,239],{},[185,237,238],{},"The signing secret is shown once, at creation."," Sendai cannot show it again afterwards —\nstore it in your secret manager immediately, alongside the API keys. If you lose it, delete\nthe endpoint and register it again to get a new secret.",[100,241,243],{"id":242},"verify-every-delivery","Verify every delivery",[86,245,246],{},"Two rules make verification work reliably:",[248,249,250,261],"ul",{},[251,252,253,256,257,260],"li",{},[185,254,255],{},"Verify the raw bytes."," Compute the HMAC over the body exactly as received, ",[95,258,259],{},"before"," any\nJSON parsing — a re-serialised body will not match.",[251,262,263,266,267,270,271,138],{},[185,264,265],{},"Compare in constant time."," Use your platform's timing-safe comparison, not ",[90,268,269],{},"==="," or\n",[90,272,273],{},"==",[275,276,278,647],"code-group",{"label":179,"title":277},"Verify",[279,280,286],"pre",{"className":281,"code":282,"filename":283,"language":284,"meta":285,"style":285},"language-js shiki shiki-themes github-light github-dark","import { createHmac, timingSafeEqual } from 'node:crypto'\nimport express from 'express'\n\nconst app = express()\n\n\u002F\u002F express.raw keeps the body as the exact bytes Sendai signed.\napp.post('\u002Fwebhooks\u002Fsendai', express.raw({ type: 'application\u002Fjson' }), (req, res) => {\n  const expected = createHmac('sha256', process.env.SENDAI_WEBHOOK_SECRET)\n    .update(req.body)\n    .digest('hex')\n  const received = req.get('X-Sendai-Signature') ?? ''\n\n  const a = Buffer.from(expected)\n  const b = Buffer.from(received)\n  if (a.length !== b.length || !timingSafeEqual(a, b)) {\n    return res.status(401).end()\n  }\n\n  const event = JSON.parse(req.body)\n  \u002F\u002F Acknowledge fast; do real work after responding.\n  res.status(200).end()\n})\n","Node.js","js","",[90,287,288,307,319,325,344,348,355,404,432,444,459,488,493,511,528,560,585,591,596,616,622,641],{"__ignoreMap":285},[289,290,292,296,300,303],"span",{"class":291,"line":33},"line",[289,293,295],{"class":294},"szBVR","import",[289,297,299],{"class":298},"sVt8B"," { createHmac, timingSafeEqual } ",[289,301,302],{"class":294},"from",[289,304,306],{"class":305},"sZZnC"," 'node:crypto'\n",[289,308,309,311,314,316],{"class":291,"line":49},[289,310,295],{"class":294},[289,312,313],{"class":298}," express ",[289,315,302],{"class":294},[289,317,318],{"class":305}," 'express'\n",[289,320,321],{"class":291,"line":7},[289,322,324],{"emptyLinePlaceholder":323},true,"\n",[289,326,327,330,334,337,341],{"class":291,"line":21},[289,328,329],{"class":294},"const",[289,331,333],{"class":332},"sj4cs"," app",[289,335,336],{"class":294}," =",[289,338,340],{"class":339},"sScJk"," express",[289,342,343],{"class":298},"()\n",[289,345,346],{"class":291,"line":38},[289,347,324],{"emptyLinePlaceholder":323},[289,349,351],{"class":291,"line":350},6,[289,352,354],{"class":353},"sJ8bj","\u002F\u002F express.raw keeps the body as the exact bytes Sendai signed.\n",[289,356,358,361,364,367,370,373,376,379,382,385,389,392,395,398,401],{"class":291,"line":357},7,[289,359,360],{"class":298},"app.",[289,362,363],{"class":339},"post",[289,365,366],{"class":298},"(",[289,368,369],{"class":305},"'\u002Fwebhooks\u002Fsendai'",[289,371,372],{"class":298},", express.",[289,374,375],{"class":339},"raw",[289,377,378],{"class":298},"({ type: ",[289,380,381],{"class":305},"'application\u002Fjson'",[289,383,384],{"class":298}," }), (",[289,386,388],{"class":387},"s4XuR","req",[289,390,391],{"class":298},", ",[289,393,394],{"class":387},"res",[289,396,397],{"class":298},") ",[289,399,400],{"class":294},"=>",[289,402,403],{"class":298}," {\n",[289,405,407,410,413,415,418,420,423,426,429],{"class":291,"line":406},8,[289,408,409],{"class":294},"  const",[289,411,412],{"class":332}," expected",[289,414,336],{"class":294},[289,416,417],{"class":339}," createHmac",[289,419,366],{"class":298},[289,421,422],{"class":305},"'sha256'",[289,424,425],{"class":298},", process.env.",[289,427,428],{"class":332},"SENDAI_WEBHOOK_SECRET",[289,430,431],{"class":298},")\n",[289,433,435,438,441],{"class":291,"line":434},9,[289,436,437],{"class":298},"    .",[289,439,440],{"class":339},"update",[289,442,443],{"class":298},"(req.body)\n",[289,445,447,449,452,454,457],{"class":291,"line":446},10,[289,448,437],{"class":298},[289,450,451],{"class":339},"digest",[289,453,366],{"class":298},[289,455,456],{"class":305},"'hex'",[289,458,431],{"class":298},[289,460,462,464,467,469,472,475,477,480,482,485],{"class":291,"line":461},11,[289,463,409],{"class":294},[289,465,466],{"class":332}," received",[289,468,336],{"class":294},[289,470,471],{"class":298}," req.",[289,473,474],{"class":339},"get",[289,476,366],{"class":298},[289,478,479],{"class":305},"'X-Sendai-Signature'",[289,481,397],{"class":298},[289,483,484],{"class":294},"??",[289,486,487],{"class":305}," ''\n",[289,489,491],{"class":291,"line":490},12,[289,492,324],{"emptyLinePlaceholder":323},[289,494,496,498,501,503,506,508],{"class":291,"line":495},13,[289,497,409],{"class":294},[289,499,500],{"class":332}," a",[289,502,336],{"class":294},[289,504,505],{"class":298}," Buffer.",[289,507,302],{"class":339},[289,509,510],{"class":298},"(expected)\n",[289,512,514,516,519,521,523,525],{"class":291,"line":513},14,[289,515,409],{"class":294},[289,517,518],{"class":332}," b",[289,520,336],{"class":294},[289,522,505],{"class":298},[289,524,302],{"class":339},[289,526,527],{"class":298},"(received)\n",[289,529,531,534,537,540,543,546,548,551,554,557],{"class":291,"line":530},15,[289,532,533],{"class":294},"  if",[289,535,536],{"class":298}," (a.",[289,538,539],{"class":332},"length",[289,541,542],{"class":294}," !==",[289,544,545],{"class":298}," b.",[289,547,539],{"class":332},[289,549,550],{"class":294}," ||",[289,552,553],{"class":294}," !",[289,555,556],{"class":339},"timingSafeEqual",[289,558,559],{"class":298},"(a, b)) {\n",[289,561,563,566,569,572,574,577,580,583],{"class":291,"line":562},16,[289,564,565],{"class":294},"    return",[289,567,568],{"class":298}," res.",[289,570,571],{"class":339},"status",[289,573,366],{"class":298},[289,575,576],{"class":332},"401",[289,578,579],{"class":298},").",[289,581,582],{"class":339},"end",[289,584,343],{"class":298},[289,586,588],{"class":291,"line":587},17,[289,589,590],{"class":298},"  }\n",[289,592,594],{"class":291,"line":593},18,[289,595,324],{"emptyLinePlaceholder":323},[289,597,599,601,604,606,609,611,614],{"class":291,"line":598},19,[289,600,409],{"class":294},[289,602,603],{"class":332}," event",[289,605,336],{"class":294},[289,607,608],{"class":332}," JSON",[289,610,138],{"class":298},[289,612,613],{"class":339},"parse",[289,615,443],{"class":298},[289,617,619],{"class":291,"line":618},20,[289,620,621],{"class":353},"  \u002F\u002F Acknowledge fast; do real work after responding.\n",[289,623,625,628,630,632,635,637,639],{"class":291,"line":624},21,[289,626,627],{"class":298},"  res.",[289,629,571],{"class":339},[289,631,366],{"class":298},[289,633,634],{"class":332},"200",[289,636,579],{"class":298},[289,638,582],{"class":339},[289,640,343],{"class":298},[289,642,644],{"class":291,"line":643},22,[289,645,646],{"class":298},"})\n",[279,648,653],{"className":649,"code":650,"filename":651,"language":652,"meta":285,"style":285},"language-python shiki shiki-themes github-light github-dark","import hashlib\nimport hmac\nimport os\n\nfrom flask import Flask, abort, request\n\napp = Flask(__name__)\nSECRET = os.environ[\"SENDAI_WEBHOOK_SECRET\"].encode()\n\n@app.post(\"\u002Fwebhooks\u002Fsendai\")\ndef sendai_webhook():\n    # request.get_data() is the raw bytes Sendai signed — before any JSON parsing.\n    raw = request.get_data()\n    expected = hmac.new(SECRET, raw, hashlib.sha256).hexdigest()\n    received = request.headers.get(\"X-Sendai-Signature\", \"\")\n\n    # hmac.compare_digest is the constant-time comparison.\n    if not hmac.compare_digest(expected, received):\n        abort(401)\n\n    event = request.get_json()\n    # Acknowledge fast; do real work after responding.\n    return \"\", 200\n","Python","python",[90,654,655,662,669,676,680,692,696,712,728,732,744,755,760,770,785,805,809,814,825,834,838,848,853],{"__ignoreMap":285},[289,656,657,659],{"class":291,"line":33},[289,658,295],{"class":294},[289,660,661],{"class":298}," hashlib\n",[289,663,664,666],{"class":291,"line":49},[289,665,295],{"class":294},[289,667,668],{"class":298}," hmac\n",[289,670,671,673],{"class":291,"line":7},[289,672,295],{"class":294},[289,674,675],{"class":298}," os\n",[289,677,678],{"class":291,"line":21},[289,679,324],{"emptyLinePlaceholder":323},[289,681,682,684,687,689],{"class":291,"line":38},[289,683,302],{"class":294},[289,685,686],{"class":298}," flask ",[289,688,295],{"class":294},[289,690,691],{"class":298}," Flask, abort, request\n",[289,693,694],{"class":291,"line":350},[289,695,324],{"emptyLinePlaceholder":323},[289,697,698,701,704,707,710],{"class":291,"line":357},[289,699,700],{"class":298},"app ",[289,702,703],{"class":294},"=",[289,705,706],{"class":298}," Flask(",[289,708,709],{"class":332},"__name__",[289,711,431],{"class":298},[289,713,714,717,719,722,725],{"class":291,"line":406},[289,715,716],{"class":332},"SECRET",[289,718,336],{"class":294},[289,720,721],{"class":298}," os.environ[",[289,723,724],{"class":305},"\"SENDAI_WEBHOOK_SECRET\"",[289,726,727],{"class":298},"].encode()\n",[289,729,730],{"class":291,"line":434},[289,731,324],{"emptyLinePlaceholder":323},[289,733,734,737,739,742],{"class":291,"line":446},[289,735,736],{"class":339},"@app.post",[289,738,366],{"class":298},[289,740,741],{"class":305},"\"\u002Fwebhooks\u002Fsendai\"",[289,743,431],{"class":298},[289,745,746,749,752],{"class":291,"line":461},[289,747,748],{"class":294},"def",[289,750,751],{"class":339}," sendai_webhook",[289,753,754],{"class":298},"():\n",[289,756,757],{"class":291,"line":490},[289,758,759],{"class":353},"    # request.get_data() is the raw bytes Sendai signed — before any JSON parsing.\n",[289,761,762,765,767],{"class":291,"line":495},[289,763,764],{"class":298},"    raw ",[289,766,703],{"class":294},[289,768,769],{"class":298}," request.get_data()\n",[289,771,772,775,777,780,782],{"class":291,"line":513},[289,773,774],{"class":298},"    expected ",[289,776,703],{"class":294},[289,778,779],{"class":298}," hmac.new(",[289,781,716],{"class":332},[289,783,784],{"class":298},", raw, hashlib.sha256).hexdigest()\n",[289,786,787,790,792,795,798,800,803],{"class":291,"line":530},[289,788,789],{"class":298},"    received ",[289,791,703],{"class":294},[289,793,794],{"class":298}," request.headers.get(",[289,796,797],{"class":305},"\"X-Sendai-Signature\"",[289,799,391],{"class":298},[289,801,802],{"class":305},"\"\"",[289,804,431],{"class":298},[289,806,807],{"class":291,"line":562},[289,808,324],{"emptyLinePlaceholder":323},[289,810,811],{"class":291,"line":587},[289,812,813],{"class":353},"    # hmac.compare_digest is the constant-time comparison.\n",[289,815,816,819,822],{"class":291,"line":593},[289,817,818],{"class":294},"    if",[289,820,821],{"class":294}," not",[289,823,824],{"class":298}," hmac.compare_digest(expected, received):\n",[289,826,827,830,832],{"class":291,"line":598},[289,828,829],{"class":298},"        abort(",[289,831,576],{"class":332},[289,833,431],{"class":298},[289,835,836],{"class":291,"line":618},[289,837,324],{"emptyLinePlaceholder":323},[289,839,840,843,845],{"class":291,"line":624},[289,841,842],{"class":298},"    event ",[289,844,703],{"class":294},[289,846,847],{"class":298}," request.get_json()\n",[289,849,850],{"class":291,"line":643},[289,851,852],{"class":353},"    # Acknowledge fast; do real work after responding.\n",[289,854,856,858,861,863],{"class":291,"line":855},23,[289,857,565],{"class":294},[289,859,860],{"class":305}," \"\"",[289,862,391],{"class":298},[289,864,865],{"class":332},"200\n",[86,867,868,869,872,873,875],{},"Both examples assume the signature is ",[185,870,871],{},"hex-encoded",". Use the dashboard's\n",[123,874,199],{"href":198}," to confirm your verification passes end-to-end before you\nrely on it in production — that check also settles the encoding question against the real\nthing rather than this page.",[100,877,879],{"id":878},"test-deliveries","Test deliveries",[86,881,882,883,885],{},"From the endpoint's row in the dashboard you can send a ",[185,884,199],{},": Sendai fires a\nreal, signed request at your URL and reports back what happened — whether it succeeded, the\nHTTP status code your endpoint returned, and the latency. A refused or failing endpoint is\nreported as a failed test, not hidden. Use it to prove connectivity and your signature check\nbefore real traffic depends on them — and to capture a real payload from your endpoint's own\nlogs.",[86,887,888,889,892],{},"The dashboard also shows each endpoint's ",[185,890,891],{},"last delivery"," — when it was, whether it\nsucceeded, and the status code — so a misbehaving endpoint is visible at a glance.",[100,894,896],{"id":895},"disable-update-delete","Disable, update, delete",[86,898,899,900,902],{},"Endpoints are managed from the same ",[185,901,210],{}," list:",[248,904,905,911,917],{},[251,906,907,910],{},[185,908,909],{},"Disable"," an endpoint to stop deliveries without losing its URL, events, or secret —\nre-enable it and deliveries resume. Useful during maintenance windows.",[251,912,913,916],{},[185,914,915],{},"Update"," its URL or event subscriptions in place; the signing secret is unchanged.",[251,918,919,922],{},[185,920,921],{},"Delete"," it to remove it entirely. The secret dies with it — registering the same URL\nagain produces a new endpoint with a new secret.",[100,924,926],{"id":925},"handling-deliveries-well","Handling deliveries well",[248,928,929,939,945],{},[251,930,931,938],{},[185,932,933,934,937],{},"Respond ",[90,935,936],{},"2xx"," quickly, process async."," Acknowledge first — enqueue the event and do the\nreal work after responding. Slow handlers show up as failing deliveries.",[251,940,941,944],{},[185,942,943],{},"Make handlers idempotent."," Key your processing on the message id plus the event name,\nso handling the same event twice is harmless — deduplication on your side costs one lookup\nand removes a whole class of bugs.",[251,946,947,950,951,955,956,958,959,961],{},[185,948,949],{},"Keep a reconciliation fallback."," A retry schedule is not part of the documented\ncontract, so treat webhooks as the fast path and poll\n",[123,952,953],{"href":125},[90,954,92],{}," on a slow interval for anything you cannot afford\nto miss — ",[90,957,120],{}," there is the same fact ",[90,960,113],{}," pushes.",[100,963,965],{"id":964},"per-send-callbacks-on-bulk","Per-send callbacks on bulk",[86,967,968,969,975,976,979],{},"Separately from account-level endpoints, ",[123,970,972],{"href":971},"\u002Fapi\u002Fsms#send-bulk-sms",[90,973,974],{},"POST \u002Fapi\u002Fv1\u002Fsms\u002Fbulk","\naccepts an optional ",[90,977,978],{},"webhook_url"," applied to every message in that one send — useful when a\nparticular campaign should report to a different URL.",[100,981,983],{"id":982},"next-steps","Next steps",[248,985,986,991,996],{},[251,987,988,989],{},"The delivery signal explained → ",[123,990,58],{"href":125},[251,992,993,994],{},"Send to many recipients → ",[123,995,68],{"href":67},[251,997,998,999],{},"Let an AI agent do the sending → ",[123,1000,1001],{"href":70},"AI agents",[1003,1004,1005],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":285,"searchDepth":49,"depth":49,"links":1007},[1008,1009,1010,1011,1012,1013,1014,1015,1016],{"id":102,"depth":49,"text":103},{"id":166,"depth":49,"text":167},{"id":203,"depth":49,"text":204},{"id":242,"depth":49,"text":243},{"id":878,"depth":49,"text":879},{"id":895,"depth":49,"text":896},{"id":925,"depth":49,"text":926},{"id":964,"depth":49,"text":965},{"id":982,"depth":49,"text":983},{"title":77,"description":80},"guides\u002Fwebhooks","md",{},1786390037513]