[{"data":1,"prerenderedAt":1174},["ShallowReactive",2],{"navigation-en":3,"en:\u002Fwebhooks\u002Fsignature-verification":193,"en:\u002Fwebhooks\u002Fsignature-verification:surround":1169},[4,20,51,77,95,110,133,158,172],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fgetting-started","1.getting-started",[10,15],{"title":11,"path":12,"stem":13,"icon":14},"Portal Preparation","\u002Fgetting-started\u002Fportal-setup","1.getting-started\u002F1.portal-setup","i-lucide-rocket",{"title":16,"path":17,"stem":18,"icon":19},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F2.quickstart","i-lucide-zap",{"title":21,"icon":22,"path":23,"stem":24,"children":25,"page":6},"Core Concepts","i-lucide-key-round","\u002Fconcepts","2.concepts",[26,31,36,41,46],{"title":27,"path":28,"stem":29,"icon":30},"Authentication","\u002Fconcepts\u002Fauthentication","2.concepts\u002F1.authentication","i-lucide-fingerprint",{"title":32,"path":33,"stem":34,"icon":35},"IP Allowlist","\u002Fconcepts\u002Fip-allowlist","2.concepts\u002F2.ip-allowlist","i-lucide-shield-check",{"title":37,"path":38,"stem":39,"icon":40},"Money Format","\u002Fconcepts\u002Fmoney","2.concepts\u002F3.money","i-lucide-banknote",{"title":42,"path":43,"stem":44,"icon":45},"Idempotency","\u002Fconcepts\u002Fidempotency","2.concepts\u002F4.idempotency","i-lucide-repeat",{"title":47,"path":48,"stem":49,"icon":50},"Error envelope & codes","\u002Fconcepts\u002Ferrors","2.concepts\u002F5.errors","i-lucide-octagon-alert",{"title":52,"icon":53,"path":54,"stem":55,"children":56,"page":6},"Deposits","i-lucide-arrow-down-to-line","\u002Fdeposits","3.deposits",[57,62,67,72],{"title":58,"path":59,"stem":60,"icon":61},"Deposit Overview & State Machine","\u002Fdeposits\u002Foverview","3.deposits\u002F1.overview","i-lucide-info",{"title":63,"path":64,"stem":65,"icon":66},"Create a Deposit","\u002Fdeposits\u002Fcreate","3.deposits\u002F2.create","i-lucide-plus",{"title":68,"path":69,"stem":70,"icon":71},"Get a Deposit","\u002Fdeposits\u002Fretrieve","3.deposits\u002F3.retrieve","i-lucide-search",{"title":73,"path":74,"stem":75,"icon":76},"Cancel a Deposit","\u002Fdeposits\u002Fcancel","3.deposits\u002F4.cancel","i-lucide-x",{"title":78,"icon":79,"path":80,"stem":81,"children":82,"page":6},"Withdrawals","i-lucide-arrow-up-from-line","\u002Fwithdrawals","4.withdrawals",[83,87,91],{"title":84,"path":85,"stem":86,"icon":61},"Withdrawal Overview","\u002Fwithdrawals\u002Foverview","4.withdrawals\u002F1.overview",{"title":88,"path":89,"stem":90,"icon":66},"Create a Withdrawal","\u002Fwithdrawals\u002Fcreate","4.withdrawals\u002F2.create",{"title":92,"path":93,"stem":94,"icon":71},"Get & List Withdrawals","\u002Fwithdrawals\u002Fretrieve","4.withdrawals\u002F3.retrieve",{"title":96,"icon":97,"path":98,"stem":99,"children":100,"page":6},"Balance & Banks","i-lucide-wallet","\u002Fbalance","5.balance",[101,105],{"title":102,"path":103,"stem":104,"icon":97},"Get Balance","\u002Fbalance\u002Fget-balance","5.balance\u002F1.get-balance",{"title":106,"path":107,"stem":108,"icon":109},"Bank List","\u002Fbalance\u002Fbanks","5.balance\u002F2.banks","i-lucide-landmark",{"title":111,"icon":112,"path":113,"stem":114,"children":115,"page":6},"Webhooks","i-lucide-webhook","\u002Fwebhooks","6.webhooks",[116,120,125,129],{"title":117,"path":118,"stem":119,"icon":61},"Webhook Overview","\u002Fwebhooks\u002Foverview","6.webhooks\u002F1.overview",{"title":121,"path":122,"stem":123,"icon":124},"Event Catalog & Payloads","\u002Fwebhooks\u002Fevents","6.webhooks\u002F2.events","i-lucide-list",{"title":126,"path":127,"stem":128,"icon":35},"Signature Verification","\u002Fwebhooks\u002Fsignature-verification","6.webhooks\u002F3.signature-verification",{"title":130,"path":131,"stem":132,"icon":45},"Endpoint Requirements, Retries & SSRF","\u002Fwebhooks\u002Fdelivery-and-retries","6.webhooks\u002F4.delivery-and-retries",{"title":134,"icon":135,"path":136,"stem":137,"children":138,"page":6},"Sandbox","i-lucide-flask-conical","\u002Fsandbox","7.sandbox",[139,143,148,153],{"title":140,"path":141,"stem":142,"icon":61},"Test Mode Overview","\u002Fsandbox\u002Foverview","7.sandbox\u002F1.overview",{"title":144,"path":145,"stem":146,"icon":147},"Simulate Transfer","\u002Fsandbox\u002Fsimulate-transfer","7.sandbox\u002F2.simulate-transfer","i-lucide-banknote-arrow-down",{"title":149,"path":150,"stem":151,"icon":152},"Top-up & Reset","\u002Fsandbox\u002Ftop-up-and-reset","7.sandbox\u002F3.top-up-and-reset","i-lucide-rotate-ccw",{"title":154,"path":155,"stem":156,"icon":157},"End-to-End Test Flow","\u002Fsandbox\u002Fe2e-test-flow","7.sandbox\u002F4.e2e-test-flow","i-lucide-list-checks",{"title":159,"icon":14,"path":160,"stem":161,"children":162,"page":6},"Go-live","\u002Fgo-live","8.go-live",[163,167],{"title":164,"path":165,"stem":166,"icon":157},"Go-live Checklist","\u002Fgo-live\u002Fchecklist","8.go-live\u002F1.checklist",{"title":168,"path":169,"stem":170,"icon":171},"Contact & Support","\u002Fgo-live\u002Fsupport","8.go-live\u002F2.support","i-lucide-life-buoy",{"title":173,"icon":174,"path":175,"stem":176,"children":177,"page":6},"Reference","i-lucide-book-marked","\u002Freference","9.reference",[178,183,188],{"title":179,"path":180,"stem":181,"icon":182},"Endpoint Catalog","\u002Freference\u002Fendpoints","9.reference\u002F1.endpoints","i-lucide-table",{"title":184,"path":185,"stem":186,"icon":187},"Code Samples (Node.js & PHP)","\u002Freference\u002Fcode-samples","9.reference\u002F2.code-samples","i-lucide-code",{"title":189,"path":190,"stem":191,"icon":192},"Status Values & Glossary","\u002Freference\u002Fglossary-states","9.reference\u002F3.glossary-states","i-lucide-book-a",{"id":194,"title":126,"badge":195,"body":196,"description":1163,"extension":1164,"links":195,"meta":1165,"method":195,"navigation":1166,"path":127,"seo":1167,"stem":128,"__hash__":1168},"docs_en\u002F6.webhooks\u002F3.signature-verification.md",null,{"type":197,"value":198,"toc":1158},"minimark",[199,203,208,278,282,288,298,314,318,1154],[200,201,202],"p",{},"Every request we send carries these HTTP headers.",[204,205,207],"h2",{"id":206},"webhook-headers","Webhook headers",[209,210,211,224],"table",{},[212,213,214],"thead",{},[215,216,217,221],"tr",{},[218,219,220],"th",{},"Header",[218,222,223],{},"Value",[225,226,227,241,260],"tbody",{},[215,228,229,236],{},[230,231,232],"td",{},[233,234,235],"code",{},"Content-Type",[230,237,238],{},[233,239,240],{},"application\u002Fjson",[215,242,243,248],{},[230,244,245],{},[233,246,247],{},"X-Webhook-Signature",[230,249,250,251,255,256,259],{},"HMAC-SHA256 of the ",[252,253,254],"strong",{},"raw request body bytes",", signed with your signing secret, encoded as ",[252,257,258],{},"hex (lowercase)",".",[215,261,262,267],{},[230,263,264],{},[233,265,266],{},"X-Webhook-Event-Id",[230,268,269,270,273,274,277],{},"The same value as ",[233,271,272],{},"event_id"," in the body (e.g. ",[233,275,276],{},"dep_abc123:deposit.success",").",[204,279,281],{"id":280},"the-algorithm","The algorithm",[200,283,284,287],{},[233,285,286],{},"HMAC-SHA256(secret, raw_body_bytes)"," → hex",[289,290,291],"ul",{},[292,293,294,297],"li",{},[233,295,296],{},"secret"," = the signing secret issued during configuration (show-once in the Portal).",[299,300,301],"warning",{},[200,302,303,306,307,310,311,259],{},[252,304,305],{},"You must sign\u002Fverify over the RAW bytes of the body you received."," Do not re-serialize the JSON before verifying — a different key order or whitespace will make the signature mismatch. Verify on the raw bytes ",[252,308,309],{},"before"," JSON parse, and compare in ",[252,312,313],{},"constant time",[204,315,317],{"id":316},"verify-on-the-merchant-side","Verify on the merchant side",[319,320,321,853],"code-group",{},[322,323,329],"pre",{"className":324,"code":325,"filename":326,"language":327,"meta":328,"style":328},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const crypto = require('crypto');\n\n\u002F\u002F Must read the raw body before parsing JSON\napp.use('\u002Fwebhooks\u002Funknownpay', express.raw({ type: 'application\u002Fjson' }));\n\napp.post('\u002Fwebhooks\u002Funknownpay', (req, res) => {\n  const secret = process.env.UNKNOWNPAY_WEBHOOK_SECRET;\n  const signature = req.header('X-Webhook-Signature') || '';\n\n  const expected = crypto.createHmac('sha256', secret)\n    .update(req.body)          \u002F\u002F req.body = Buffer of raw bytes\n    .digest('hex');\n\n  const ok = signature.length === expected.length &&\n    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));\n  if (!ok) return res.status(401).send('bad signature');\n\n  const event = JSON.parse(req.body.toString('utf8'));\n  \u002F\u002F ... idempotency on event.event_id, then process ...\n  res.sendStatus(200);\n});\n","Node.js","js","",[233,330,331,370,377,384,442,447,487,514,551,556,590,614,635,640,669,715,768,773,817,823,843],{"__ignoreMap":328},[332,333,336,340,344,348,352,355,358,362,364,367],"span",{"class":334,"line":335},"line",1,[332,337,339],{"class":338},"spNyl","const",[332,341,343],{"class":342},"sTEyZ"," crypto ",[332,345,347],{"class":346},"sMK4o","=",[332,349,351],{"class":350},"s2Zo4"," require",[332,353,354],{"class":342},"(",[332,356,357],{"class":346},"'",[332,359,361],{"class":360},"sfazB","crypto",[332,363,357],{"class":346},[332,365,366],{"class":342},")",[332,368,369],{"class":346},";\n",[332,371,373],{"class":334,"line":372},2,[332,374,376],{"emptyLinePlaceholder":375},true,"\n",[332,378,380],{"class":334,"line":379},3,[332,381,383],{"class":382},"sHwdD","\u002F\u002F Must read the raw body before parsing JSON\n",[332,385,387,390,392,395,397,399,402,404,407,410,412,415,417,420,424,427,430,432,434,437,440],{"class":334,"line":386},4,[332,388,389],{"class":342},"app",[332,391,259],{"class":346},[332,393,394],{"class":350},"use",[332,396,354],{"class":342},[332,398,357],{"class":346},[332,400,401],{"class":360},"\u002Fwebhooks\u002Funknownpay",[332,403,357],{"class":346},[332,405,406],{"class":346},",",[332,408,409],{"class":342}," express",[332,411,259],{"class":346},[332,413,414],{"class":350},"raw",[332,416,354],{"class":342},[332,418,419],{"class":346},"{",[332,421,423],{"class":422},"swJcz"," type",[332,425,426],{"class":346},":",[332,428,429],{"class":346}," '",[332,431,240],{"class":360},[332,433,357],{"class":346},[332,435,436],{"class":346}," }",[332,438,439],{"class":342},"))",[332,441,369],{"class":346},[332,443,445],{"class":334,"line":444},5,[332,446,376],{"emptyLinePlaceholder":375},[332,448,450,452,454,457,459,461,463,465,467,470,474,476,479,481,484],{"class":334,"line":449},6,[332,451,389],{"class":342},[332,453,259],{"class":346},[332,455,456],{"class":350},"post",[332,458,354],{"class":342},[332,460,357],{"class":346},[332,462,401],{"class":360},[332,464,357],{"class":346},[332,466,406],{"class":346},[332,468,469],{"class":346}," (",[332,471,473],{"class":472},"sHdIc","req",[332,475,406],{"class":346},[332,477,478],{"class":472}," res",[332,480,366],{"class":346},[332,482,483],{"class":338}," =>",[332,485,486],{"class":346}," {\n",[332,488,490,493,496,499,502,504,507,509,512],{"class":334,"line":489},7,[332,491,492],{"class":338},"  const",[332,494,495],{"class":342}," secret",[332,497,498],{"class":346}," =",[332,500,501],{"class":342}," process",[332,503,259],{"class":346},[332,505,506],{"class":342},"env",[332,508,259],{"class":346},[332,510,511],{"class":342},"UNKNOWNPAY_WEBHOOK_SECRET",[332,513,369],{"class":346},[332,515,517,519,522,524,527,529,532,534,536,538,540,543,546,549],{"class":334,"line":516},8,[332,518,492],{"class":338},[332,520,521],{"class":342}," signature",[332,523,498],{"class":346},[332,525,526],{"class":342}," req",[332,528,259],{"class":346},[332,530,531],{"class":350},"header",[332,533,354],{"class":422},[332,535,357],{"class":346},[332,537,247],{"class":360},[332,539,357],{"class":346},[332,541,542],{"class":422},") ",[332,544,545],{"class":346},"||",[332,547,548],{"class":346}," ''",[332,550,369],{"class":346},[332,552,554],{"class":334,"line":553},9,[332,555,376],{"emptyLinePlaceholder":375},[332,557,559,561,564,566,569,571,574,576,578,581,583,585,587],{"class":334,"line":558},10,[332,560,492],{"class":338},[332,562,563],{"class":342}," expected",[332,565,498],{"class":346},[332,567,568],{"class":342}," crypto",[332,570,259],{"class":346},[332,572,573],{"class":350},"createHmac",[332,575,354],{"class":422},[332,577,357],{"class":346},[332,579,580],{"class":360},"sha256",[332,582,357],{"class":346},[332,584,406],{"class":346},[332,586,495],{"class":342},[332,588,589],{"class":422},")\n",[332,591,593,596,599,601,603,605,608,611],{"class":334,"line":592},11,[332,594,595],{"class":346},"    .",[332,597,598],{"class":350},"update",[332,600,354],{"class":422},[332,602,473],{"class":342},[332,604,259],{"class":346},[332,606,607],{"class":342},"body",[332,609,610],{"class":422},")          ",[332,612,613],{"class":382},"\u002F\u002F req.body = Buffer of raw bytes\n",[332,615,617,619,622,624,626,629,631,633],{"class":334,"line":616},12,[332,618,595],{"class":346},[332,620,621],{"class":350},"digest",[332,623,354],{"class":422},[332,625,357],{"class":346},[332,627,628],{"class":360},"hex",[332,630,357],{"class":346},[332,632,366],{"class":422},[332,634,369],{"class":346},[332,636,638],{"class":334,"line":637},13,[332,639,376],{"emptyLinePlaceholder":375},[332,641,643,645,648,650,652,654,657,660,662,664,666],{"class":334,"line":642},14,[332,644,492],{"class":338},[332,646,647],{"class":342}," ok",[332,649,498],{"class":346},[332,651,521],{"class":342},[332,653,259],{"class":346},[332,655,656],{"class":342},"length",[332,658,659],{"class":346}," ===",[332,661,563],{"class":342},[332,663,259],{"class":346},[332,665,656],{"class":342},[332,667,668],{"class":346}," &&\n",[332,670,672,675,677,680,682,685,687,690,692,695,697,699,702,704,706,708,711,713],{"class":334,"line":671},15,[332,673,674],{"class":342},"    crypto",[332,676,259],{"class":346},[332,678,679],{"class":350},"timingSafeEqual",[332,681,354],{"class":422},[332,683,684],{"class":342},"Buffer",[332,686,259],{"class":346},[332,688,689],{"class":350},"from",[332,691,354],{"class":422},[332,693,694],{"class":342},"signature",[332,696,366],{"class":422},[332,698,406],{"class":346},[332,700,701],{"class":342}," Buffer",[332,703,259],{"class":346},[332,705,689],{"class":350},[332,707,354],{"class":422},[332,709,710],{"class":342},"expected",[332,712,439],{"class":422},[332,714,369],{"class":346},[332,716,718,722,724,727,730,732,735,737,739,742,744,748,750,752,755,757,759,762,764,766],{"class":334,"line":717},16,[332,719,721],{"class":720},"s7zQu","  if",[332,723,469],{"class":422},[332,725,726],{"class":346},"!",[332,728,729],{"class":342},"ok",[332,731,542],{"class":422},[332,733,734],{"class":720},"return",[332,736,478],{"class":342},[332,738,259],{"class":346},[332,740,741],{"class":350},"status",[332,743,354],{"class":422},[332,745,747],{"class":746},"sbssI","401",[332,749,366],{"class":422},[332,751,259],{"class":346},[332,753,754],{"class":350},"send",[332,756,354],{"class":422},[332,758,357],{"class":346},[332,760,761],{"class":360},"bad signature",[332,763,357],{"class":346},[332,765,366],{"class":422},[332,767,369],{"class":346},[332,769,771],{"class":334,"line":770},17,[332,772,376],{"emptyLinePlaceholder":375},[332,774,776,778,781,783,786,788,791,793,795,797,799,801,804,806,808,811,813,815],{"class":334,"line":775},18,[332,777,492],{"class":338},[332,779,780],{"class":342}," event",[332,782,498],{"class":346},[332,784,785],{"class":342}," JSON",[332,787,259],{"class":346},[332,789,790],{"class":350},"parse",[332,792,354],{"class":422},[332,794,473],{"class":342},[332,796,259],{"class":346},[332,798,607],{"class":342},[332,800,259],{"class":346},[332,802,803],{"class":350},"toString",[332,805,354],{"class":422},[332,807,357],{"class":346},[332,809,810],{"class":360},"utf8",[332,812,357],{"class":346},[332,814,439],{"class":422},[332,816,369],{"class":346},[332,818,820],{"class":334,"line":819},19,[332,821,822],{"class":382},"  \u002F\u002F ... idempotency on event.event_id, then process ...\n",[332,824,826,829,831,834,836,839,841],{"class":334,"line":825},20,[332,827,828],{"class":342},"  res",[332,830,259],{"class":346},[332,832,833],{"class":350},"sendStatus",[332,835,354],{"class":422},[332,837,838],{"class":746},"200",[332,840,366],{"class":422},[332,842,369],{"class":346},[332,844,846,849,851],{"class":334,"line":845},21,[332,847,848],{"class":346},"}",[332,850,366],{"class":342},[332,852,369],{"class":346},[322,854,859],{"className":855,"code":856,"filename":857,"language":858,"meta":328,"style":328},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import hmac, hashlib, os\nfrom flask import Flask, request, abort\n\napp = Flask(__name__)\n\n@app.post(\"\u002Fwebhooks\u002Funknownpay\")\ndef webhook():\n    secret = os.environ[\"UNKNOWNPAY_WEBHOOK_SECRET\"].encode()\n    raw = request.get_data()  # raw bytes — do not use request.json\n    expected = hmac.new(secret, raw, hashlib.sha256).hexdigest()\n    got = request.headers.get(\"X-Webhook-Signature\", \"\")\n    if not hmac.compare_digest(got, expected):\n        abort(401)\n    event = request.get_json()\n    # ... idempotency on event[\"event_id\"], then process ...\n    return \"\", 200\n","Python","python",[233,860,861,879,901,905,921,925,947,958,991,1011,1049,1083,1110,1121,1137,1142],{"__ignoreMap":328},[332,862,863,866,869,871,874,876],{"class":334,"line":335},[332,864,865],{"class":720},"import",[332,867,868],{"class":342}," hmac",[332,870,406],{"class":346},[332,872,873],{"class":342}," hashlib",[332,875,406],{"class":346},[332,877,878],{"class":342}," os\n",[332,880,881,883,886,888,891,893,896,898],{"class":334,"line":372},[332,882,689],{"class":720},[332,884,885],{"class":342}," flask ",[332,887,865],{"class":720},[332,889,890],{"class":342}," Flask",[332,892,406],{"class":346},[332,894,895],{"class":342}," request",[332,897,406],{"class":346},[332,899,900],{"class":342}," abort\n",[332,902,903],{"class":334,"line":379},[332,904,376],{"emptyLinePlaceholder":375},[332,906,907,910,912,914,916,919],{"class":334,"line":386},[332,908,909],{"class":342},"app ",[332,911,347],{"class":346},[332,913,890],{"class":350},[332,915,354],{"class":346},[332,917,918],{"class":342},"__name__",[332,920,589],{"class":346},[332,922,923],{"class":334,"line":444},[332,924,376],{"emptyLinePlaceholder":375},[332,926,927,930,932,934,936,938,941,943,945],{"class":334,"line":449},[332,928,929],{"class":346},"@",[332,931,389],{"class":350},[332,933,259],{"class":346},[332,935,456],{"class":350},[332,937,354],{"class":346},[332,939,940],{"class":346},"\"",[332,942,401],{"class":360},[332,944,940],{"class":346},[332,946,589],{"class":346},[332,948,949,952,955],{"class":334,"line":489},[332,950,951],{"class":338},"def",[332,953,954],{"class":350}," webhook",[332,956,957],{"class":346},"():\n",[332,959,960,963,965,968,970,973,976,978,980,982,985,988],{"class":334,"line":516},[332,961,962],{"class":342},"    secret ",[332,964,347],{"class":346},[332,966,967],{"class":342}," os",[332,969,259],{"class":346},[332,971,972],{"class":422},"environ",[332,974,975],{"class":346},"[",[332,977,940],{"class":346},[332,979,511],{"class":360},[332,981,940],{"class":346},[332,983,984],{"class":346},"].",[332,986,987],{"class":350},"encode",[332,989,990],{"class":346},"()\n",[332,992,993,996,998,1000,1002,1005,1008],{"class":334,"line":553},[332,994,995],{"class":342},"    raw ",[332,997,347],{"class":346},[332,999,895],{"class":342},[332,1001,259],{"class":346},[332,1003,1004],{"class":350},"get_data",[332,1006,1007],{"class":346},"()",[332,1009,1010],{"class":382},"  # raw bytes — do not use request.json\n",[332,1012,1013,1016,1018,1020,1022,1025,1027,1029,1031,1034,1036,1038,1040,1042,1044,1047],{"class":334,"line":558},[332,1014,1015],{"class":342},"    expected ",[332,1017,347],{"class":346},[332,1019,868],{"class":342},[332,1021,259],{"class":346},[332,1023,1024],{"class":350},"new",[332,1026,354],{"class":346},[332,1028,296],{"class":350},[332,1030,406],{"class":346},[332,1032,1033],{"class":350}," raw",[332,1035,406],{"class":346},[332,1037,873],{"class":350},[332,1039,259],{"class":346},[332,1041,580],{"class":422},[332,1043,277],{"class":346},[332,1045,1046],{"class":350},"hexdigest",[332,1048,990],{"class":346},[332,1050,1051,1054,1056,1058,1060,1063,1065,1068,1070,1072,1074,1076,1078,1081],{"class":334,"line":592},[332,1052,1053],{"class":342},"    got ",[332,1055,347],{"class":346},[332,1057,895],{"class":342},[332,1059,259],{"class":346},[332,1061,1062],{"class":422},"headers",[332,1064,259],{"class":346},[332,1066,1067],{"class":350},"get",[332,1069,354],{"class":346},[332,1071,940],{"class":346},[332,1073,247],{"class":360},[332,1075,940],{"class":346},[332,1077,406],{"class":346},[332,1079,1080],{"class":346}," \"\"",[332,1082,589],{"class":346},[332,1084,1085,1088,1091,1093,1095,1098,1100,1103,1105,1107],{"class":334,"line":616},[332,1086,1087],{"class":720},"    if",[332,1089,1090],{"class":346}," not",[332,1092,868],{"class":342},[332,1094,259],{"class":346},[332,1096,1097],{"class":350},"compare_digest",[332,1099,354],{"class":346},[332,1101,1102],{"class":350},"got",[332,1104,406],{"class":346},[332,1106,563],{"class":350},[332,1108,1109],{"class":346},"):\n",[332,1111,1112,1115,1117,1119],{"class":334,"line":637},[332,1113,1114],{"class":350},"        abort",[332,1116,354],{"class":346},[332,1118,747],{"class":746},[332,1120,589],{"class":346},[332,1122,1123,1126,1128,1130,1132,1135],{"class":334,"line":642},[332,1124,1125],{"class":342},"    event ",[332,1127,347],{"class":346},[332,1129,895],{"class":342},[332,1131,259],{"class":346},[332,1133,1134],{"class":350},"get_json",[332,1136,990],{"class":346},[332,1138,1139],{"class":334,"line":671},[332,1140,1141],{"class":382},"    # ... idempotency on event[\"event_id\"], then process ...\n",[332,1143,1144,1147,1149,1151],{"class":334,"line":717},[332,1145,1146],{"class":720},"    return",[332,1148,1080],{"class":346},[332,1150,406],{"class":346},[332,1152,1153],{"class":746}," 200\n",[1155,1156,1157],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .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 .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);}",{"title":328,"searchDepth":335,"depth":372,"links":1159},[1160,1161,1162],{"id":206,"depth":372,"text":207},{"id":280,"depth":372,"text":281},{"id":316,"depth":372,"text":317},"Verify the X-Webhook-Signature HMAC-SHA256 on the raw request bytes before parsing JSON, with Node.js and Python examples","md",{},{"icon":35},{"title":126,"description":1163},"Q_Mt110XCOmHgl96BYAntNMnofaa8JFrwElU5qO2wZE",[1170,1172],{"title":121,"path":122,"stem":123,"description":1171,"icon":124,"children":-1},"Every webhook event UnknownPay actually sends, plus the shared payload fields and real JSON examples for deposits and withdrawals",{"title":130,"path":131,"stem":132,"description":1173,"icon":45,"children":-1},"What your webhook endpoint must do, the retry\u002Fbackoff schedule, replay, and the HTTPS\u002FSSRF rules that reject an INVALID_URL",1781891155528]