[{"data":1,"prerenderedAt":2179},["ShallowReactive",2],{"navigation-en":3,"en:\u002Fconcepts\u002Fauthentication":193,"en:\u002Fconcepts\u002Fauthentication:surround":2174},[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":27,"badge":195,"body":196,"description":2168,"extension":2169,"links":195,"meta":2170,"method":195,"navigation":2171,"path":28,"seo":2172,"stem":29,"__hash__":2173},"docs_en\u002F2.concepts\u002F1.authentication.md",null,{"type":197,"value":198,"toc":2160},"minimark",[199,229,247,265,270,285,343,348,391,402,427,431,435,439,450,460,552,555,561,588,607,611,664,670,673,677,716,719,730,735,847,853,875,879,915,919,2135,2153,2156],[200,201,202,203,207,208,212,213,216,217,220,221,224,225,228],"p",{},"Every request your merchant server makes to the UnknownPay S2S API (e.g. ",[204,205,206],"code",{},"POST \u002Fv1\u002Fdeposits",") must be signed with ",[209,210,211],"strong",{},"HMAC-SHA256"," using your merchant API key + secret. The system ",[209,214,215],{},"never accepts a bare API key"," — a valid signature (",[204,218,219],{},"X-Signature",") and timestamp (",[204,222,223],{},"X-Timestamp",") are always required, otherwise the request is rejected with ",[204,226,227],{},"401",".",[230,231,232],"warning",{},[200,233,234,237,238,240,241,243,244,228],{},[209,235,236],{},"Every request must be HMAC-signed."," There is no \"API key only\" mode. A request missing ",[204,239,219],{}," \u002F ",[204,242,223],{},", or carrying a signature that does not match, is rejected with ",[204,245,246],{},"401 UNAUTHORIZED",[248,249,250],"note",{},[200,251,252,253,256,257,260,261,264],{},"Money note: every money field on the wire is a ",[209,254,255],{},"baht string with 2 decimal places",", e.g. ",[204,258,259],{},"\"100.50\""," (not a number, not satang). This is unrelated to signing, but worth repeating because the body you sign contains these fields (for the full money rules see ",[262,263,37],"a",{"href":38},").",[266,267,269],"h2",{"id":268},"_1-api-key-and-secret-format","1. API key and secret format",[200,271,272,273,276,277,280,281,284],{},"A merchant receives one credential set per mode, consisting of a ",[209,274,275],{},"key id"," (sent in the header) and a ",[209,278,279],{},"secret"," (used to sign, never sent on the wire). Issuing\u002Frotating credentials happens in the Portal (see ",[262,282,283],{"href":12},"Portal Preparation → rotate secret","):",[286,287,288,304],"table",{},[289,290,291],"thead",{},[292,293,294,298,301],"tr",{},[295,296,297],"th",{},"Component",[295,299,300],{},"Example",[295,302,303],{},"Description",[305,306,307,327],"tbody",{},[292,308,309,315,320],{},[310,311,312],"td",{},[204,313,314],{},"key_id",[310,316,317],{},[204,318,319],{},"unk_live_1a2b3c4d5e6f...",[310,321,322,323,326],{},"Public identifier, placed in the ",[204,324,325],{},"X-Api-Key"," header",[292,328,329,333,336],{},[310,330,331],{},[204,332,279],{},[310,334,335],{},"(a 64-character hex string)",[310,337,338,339,342],{},"Secret key for HMAC — ",[209,340,341],{},"shown only once",", at rotate time",[200,344,345],{},[209,346,347],{},"Distinguishing live \u002F test from the key id prefix:",[286,349,350,363],{},[289,351,352],{},[292,353,354,357,360],{},[295,355,356],{},"Prefix",[295,358,359],{},"Mode",[295,361,362],{},"Meaning",[305,364,365,378],{},[292,366,367,372,375],{},[310,368,369],{},[204,370,371],{},"unk_live_",[310,373,374],{},"live",[310,376,377],{},"Real transactions",[292,379,380,385,388],{},[310,381,382],{},[204,383,384],{},"unk_test_",[310,386,387],{},"test",[310,389,390],{},"sandbox \u002F testing",[200,392,393,394,397,398,401],{},"The mode (live\u002Ftest) is ",[209,395,396],{},"derived from the API key on the server side"," (server-derived), not from the URL or host — the key id is the only source of truth for the mode. So you ",[209,399,400],{},"switch live\u002Ftest by changing the key only",", never by changing the endpoint.",[403,404,405,413,420],"ul",{},[406,407,408,409,412],"li",{},"A single merchant may hold at most ",[209,410,411],{},"1 live + 1 test"," active key at the same time (separate sets, no overlap).",[406,414,415,416,419],{},"The secret is ",[209,417,418],{},"stored encrypted (envelope encryption)"," on the UnknownPay side — the system decrypts it only at verify time, never logs it, and never returns it, except at rotate (show-once).",[406,421,422,423,426],{},"If you lose the secret, you must issue\u002Frotate a new secret in the Portal, which ",[209,424,425],{},"revokes the old key for that mode immediately"," and returns the new secret once.",[428,429],"placeholder-image",{"subject":430},"Portal page showing the rotate-secret button and the show-once secret box with the warning 'copy it now, it will not be shown again'",[432,433],"placeholder-note",{"value":434},"the secret length\u002Fformat to show merchants in the docs (the code generates a 64-character hex string)",[266,436,438],{"id":437},"_2-canonical-signing-string-must-be-signed-exactly-like-this","2. Canonical signing string (must be signed exactly like this)",[200,440,441,442,449],{},"The signature is computed from a string assembled from ",[209,443,444,445,448],{},"4 lines, joined by a plain ",[204,446,447],{},"\\n"," (newline)",", in exactly this order:",[451,452,457],"pre",{"className":453,"code":455,"language":456},[454],"language-text","\u003CHTTP_METHOD>\\n\u003CREQUEST_TARGET>\\n\u003CTIMESTAMP>\\n\u003CBODY_SHA256_HEX>\n","text",[204,458,455],{"__ignoreMap":459},"",[286,461,462,475],{},[289,463,464],{},[292,465,466,469,472],{},[295,467,468],{},"Line",[295,470,471],{},"Value",[295,473,474],{},"Source",[305,476,477,495,520,537],{},[292,478,479,482,485],{},[310,480,481],{},"1",[310,483,484],{},"HTTP method",[310,486,487,488,491,492],{},"Uppercase, e.g. ",[204,489,490],{},"POST",", ",[204,493,494],{},"GET",[292,496,497,500,506],{},[310,498,499],{},"2",[310,501,502,503],{},"request target = ",[209,504,505],{},"path + query string",[310,507,508,509,512,513,516,517],{},"e.g. ",[204,510,511],{},"\u002Fv1\u002Fdeposits"," or ",[204,514,515],{},"\u002Fv1\u002Fdeposits?foo=1"," — ",[209,518,519],{},"the query is part of the signature too",[292,521,522,525,528],{},[310,523,524],{},"3",[310,526,527],{},"timestamp",[310,529,530,531,534,535],{},"Unix epoch ",[209,532,533],{},"seconds"," (numeric string) — the same value sent in ",[204,536,223],{},[292,538,539,542,549],{},[310,540,541],{},"4",[310,543,544,545,548],{},"SHA-256 of the raw request body, ",[209,546,547],{},"hex-encoded"," (lowercase)",[310,550,551],{},"See section 5",[200,553,554],{},"Then:",[451,556,559],{"className":557,"code":558,"language":456},[454],"signature = HEX( HMAC_SHA256( key = secret, message = canonical_string ) )\n",[204,560,558],{"__ignoreMap":459},[403,562,563,568,574,581],{},[406,564,565,566],{},"Algorithm: ",[209,567,211],{},[406,569,570,571,573],{},"Key: ",[204,572,279],{}," (used as the raw bytes of the secret string)",[406,575,576,577,580],{},"Output encoding: ",[209,578,579],{},"hex (lowercase)"," — not base64",[406,582,583,584,587],{},"The server-side signature comparison is a ",[209,585,586],{},"constant-time compare"," (to prevent timing attacks)",[230,589,590],{},[200,591,592,593,596,597,599,600,603,604,606],{},"Line 2 must be the path ",[209,594,595],{},"with the query string actually sent",". If you sign ",[204,598,511],{}," but call ",[204,601,602],{},"\u002Fv1\u002Fdeposits?evil=1",", you get a ",[204,605,227],{}," (this case is tested) — the query string cannot be altered\u002Fappended after signing.",[266,608,610],{"id":609},"_3-http-headers-required-on-every-request","3. HTTP headers required on every request",[286,612,613,625],{},[289,614,615],{},[292,616,617,620,623],{},[295,618,619],{},"Header",[295,621,622],{},"Required",[295,624,471],{},[305,626,627,642,653],{},[292,628,629,633,636],{},[310,630,631],{},[204,632,325],{},[310,634,635],{},"✅",[310,637,638,639],{},"The merchant key id, e.g. ",[204,640,641],{},"unk_live_...",[292,643,644,648,650],{},[310,645,646],{},[204,647,219],{},[310,649,635],{},[310,651,652],{},"The HMAC-SHA256 signature as hex (from section 2)",[292,654,655,659,661],{},[310,656,657],{},[204,658,223],{},[310,660,635],{},[310,662,663],{},"Unix epoch seconds (numeric string) — must match line 3 of the canonical string",[200,665,666,667,669],{},"If any one of these 3 headers is missing (empty value) → ",[204,668,246],{}," immediately.",[432,671],{"value":672},"whether the merchant must also send Content-Type: application\u002Fjson on POST (the verify code does not check Content-Type, but the create handler might)",[266,674,676],{"id":675},"_4-replay-window-and-the-error-when-the-timestamp-is-out-of-range","4. Replay window and the error when the timestamp is out of range",[403,678,679,686,701],{},[406,680,681,682,685],{},"The replay window is ",[209,683,684],{},"±300 seconds (±5 minutes)"," from server time.",[406,687,688,689,692,693,696,697,700],{},"The system computes ",[204,690,691],{},"delta = server_now - X-Timestamp",". If ",[204,694,695],{},"delta > 300"," (too old) or ",[204,698,699],{},"delta \u003C -300"," (too far in the future) → rejected.",[406,702,703,704,708,709,712,713,715],{},"The resulting error is ",[209,705,706],{},[204,707,227],{}," with body code ",[204,710,711],{},"UNAUTHORIZED"," (the system does not return a distinct error code for an out-of-range timestamp — it is the same ",[204,714,246],{}," as a bad signature, so as not to reveal the cause).",[200,717,718],{},"Best practices:",[403,720,721,724],{},[406,722,723],{},"Keep your server clock synced with NTP.",[406,725,726,727,729],{},"Generate a fresh ",[204,728,223],{}," for every request (do not cache it) and re-sign every time, because the timestamp is part of the canonical string.",[200,731,732],{},[209,733,734],{},"Example error envelope (the real shape from the system):",[451,736,740],{"className":737,"code":738,"language":739,"meta":459,"style":459},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"error\": {\n    \"code\": \"UNAUTHORIZED\",\n    \"message\": \"unauthorized\",\n    \"request_id\": \"...\"\n  }\n}\n","json",[204,741,742,751,770,794,815,835,841],{"__ignoreMap":459},[743,744,747],"span",{"class":745,"line":746},"line",1,[743,748,750],{"class":749},"sMK4o","{\n",[743,752,754,757,761,764,767],{"class":745,"line":753},2,[743,755,756],{"class":749},"  \"",[743,758,760],{"class":759},"spNyl","error",[743,762,763],{"class":749},"\"",[743,765,766],{"class":749},":",[743,768,769],{"class":749}," {\n",[743,771,773,776,779,781,783,786,789,791],{"class":745,"line":772},3,[743,774,775],{"class":749},"    \"",[743,777,204],{"class":778},"sBMFI",[743,780,763],{"class":749},[743,782,766],{"class":749},[743,784,785],{"class":749}," \"",[743,787,711],{"class":788},"sfazB",[743,790,763],{"class":749},[743,792,793],{"class":749},",\n",[743,795,797,799,802,804,806,808,811,813],{"class":745,"line":796},4,[743,798,775],{"class":749},[743,800,801],{"class":778},"message",[743,803,763],{"class":749},[743,805,766],{"class":749},[743,807,785],{"class":749},[743,809,810],{"class":788},"unauthorized",[743,812,763],{"class":749},[743,814,793],{"class":749},[743,816,818,820,823,825,827,829,832],{"class":745,"line":817},5,[743,819,775],{"class":749},[743,821,822],{"class":778},"request_id",[743,824,763],{"class":749},[743,826,766],{"class":749},[743,828,785],{"class":749},[743,830,831],{"class":788},"...",[743,833,834],{"class":749},"\"\n",[743,836,838],{"class":745,"line":837},6,[743,839,840],{"class":749},"  }\n",[743,842,844],{"class":745,"line":843},7,[743,845,846],{"class":749},"}\n",[200,848,849,850,852],{},"The cases\u002Fcauses that lead to ",[204,851,246],{}," are as follows (the system answers identically to all of them so as not to give hints):",[403,854,855,864,867,872],{},[406,856,857,858,240,860,240,862],{},"Missing ",[204,859,325],{},[204,861,219],{},[204,863,223],{},[406,865,866],{},"An unknown key id, or one that has been revoked (e.g. superseded by a rotate)",[406,868,869,871],{},[204,870,223],{}," is not numeric, or is outside the ±300s window",[406,873,874],{},"The signature does not match (body altered, query altered, wrong secret, etc.)",[266,876,878],{"id":877},"_5-computing-the-body-hash-including-the-get-no-body-case","5. Computing the body hash (including the GET \u002F no-body case)",[403,880,881,888,895],{},[406,882,883,884,887],{},"The body hash is computed from the ",[209,885,886],{},"raw bytes of the request body exactly as sent on the wire"," (raw bytes, not decoded\u002Fdecompressed) — you must sign from the same set of bytes you send (do not re-serialize the JSON after signing, because a different key ordering\u002Fwhitespace will change the hash).",[406,889,890,891,894],{},"Formula: ",[204,892,893],{},"sha256( raw_body_bytes )"," then hex-encode (lowercase) → place as line 4.",[406,896,897,900,901,904,905,911,914],{},[209,898,899],{},"For GET or any request with no body:"," the body is an empty byte array (",[204,902,903],{},"\"\"",", length 0), so the body hash is the SHA-256 of the empty string, which is the constant:",[451,906,909],{"className":907,"code":908,"language":456},[454],"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n",[204,910,908],{"__ignoreMap":459},[912,913],"br",{},"You can use this value directly as line 4 for any request with no body.",[266,916,918],{"id":917},"_6-signing-examples","6. Signing examples",[920,921,922,929,1466,1775],"code-group",{},[451,923,927],{"className":924,"code":925,"filename":926,"language":456,"meta":459},[454],"ts        = unix_seconds_now()              \u002F\u002F e.g. \"1718800000\"\nbody      = raw bytes to send (POST: JSON; GET: empty)\nbody_hash = hex( sha256(body) )\ntarget    = path + (\"?\" + query if any)     \u002F\u002F e.g. \"\u002Fv1\u002Fdeposits\"\ncanonical = METHOD + \"\\n\" + target + \"\\n\" + ts + \"\\n\" + body_hash\nsignature = hex( hmac_sha256(secret, canonical) )\n\nheaders:\n  X-Api-Key   = key_id\n  X-Signature = signature\n  X-Timestamp = ts\n","Pseudocode",[204,928,925],{"__ignoreMap":459},[451,930,935],{"className":931,"code":932,"filename":933,"language":934,"meta":459,"style":459},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const crypto = require(\"crypto\");\n\nfunction signRequest({ secret, method, target, body }) {\n  \u002F\u002F body is a Buffer\u002Fstring exactly as sent; for GET use \"\" (empty)\n  const raw = Buffer.from(body || \"\");\n  const ts = Math.floor(Date.now() \u002F 1000).toString();\n  const bodyHash = crypto.createHash(\"sha256\").update(raw).digest(\"hex\");\n  const canonical = `${method}\\n${target}\\n${ts}\\n${bodyHash}`;\n  const signature = crypto\n    .createHmac(\"sha256\", secret)\n    .update(canonical)\n    .digest(\"hex\");\n  return { ts, signature };\n}\n\n\u002F\u002F Example usage\nconst secret = \"\u003C\u003CYOUR_SECRET>>\";\nconst body = JSON.stringify({ amount: \"100.50\" }); \u002F\u002F money = baht string!\nconst { ts, signature } = signRequest({\n  secret,\n  method: \"POST\",\n  target: \"\u002Fv1\u002Fdeposits\",\n  body,\n});\n\u002F\u002F Send: X-Api-Key, X-Signature=signature, X-Timestamp=ts, body=body (same bytes)\n","Node.js","javascript",[204,936,937,969,975,1011,1017,1052,1101,1159,1209,1222,1246,1260,1279,1298,1303,1308,1314,1333,1379,1403,1411,1427,1443,1451,1460],{"__ignoreMap":459},[743,938,939,942,946,949,953,956,958,961,963,966],{"class":745,"line":746},[743,940,941],{"class":759},"const",[743,943,945],{"class":944},"sTEyZ"," crypto ",[743,947,948],{"class":749},"=",[743,950,952],{"class":951},"s2Zo4"," require",[743,954,955],{"class":944},"(",[743,957,763],{"class":749},[743,959,960],{"class":788},"crypto",[743,962,763],{"class":749},[743,964,965],{"class":944},")",[743,967,968],{"class":749},";\n",[743,970,971],{"class":745,"line":753},[743,972,974],{"emptyLinePlaceholder":973},true,"\n",[743,976,977,980,983,986,990,993,996,998,1001,1003,1006,1009],{"class":745,"line":772},[743,978,979],{"class":759},"function",[743,981,982],{"class":951}," signRequest",[743,984,985],{"class":749},"({",[743,987,989],{"class":988},"sHdIc"," secret",[743,991,992],{"class":749},",",[743,994,995],{"class":988}," method",[743,997,992],{"class":749},[743,999,1000],{"class":988}," target",[743,1002,992],{"class":749},[743,1004,1005],{"class":988}," body",[743,1007,1008],{"class":749}," })",[743,1010,769],{"class":749},[743,1012,1013],{"class":745,"line":796},[743,1014,1016],{"class":1015},"sHwdD","  \u002F\u002F body is a Buffer\u002Fstring exactly as sent; for GET use \"\" (empty)\n",[743,1018,1019,1022,1025,1028,1031,1033,1036,1039,1042,1045,1048,1050],{"class":745,"line":817},[743,1020,1021],{"class":759},"  const",[743,1023,1024],{"class":944}," raw",[743,1026,1027],{"class":749}," =",[743,1029,1030],{"class":944}," Buffer",[743,1032,228],{"class":749},[743,1034,1035],{"class":951},"from",[743,1037,955],{"class":1038},"swJcz",[743,1040,1041],{"class":944},"body",[743,1043,1044],{"class":749}," ||",[743,1046,1047],{"class":749}," \"\"",[743,1049,965],{"class":1038},[743,1051,968],{"class":749},[743,1053,1054,1056,1059,1061,1064,1066,1069,1071,1074,1076,1079,1082,1085,1089,1091,1093,1096,1099],{"class":745,"line":837},[743,1055,1021],{"class":759},[743,1057,1058],{"class":944}," ts",[743,1060,1027],{"class":749},[743,1062,1063],{"class":944}," Math",[743,1065,228],{"class":749},[743,1067,1068],{"class":951},"floor",[743,1070,955],{"class":1038},[743,1072,1073],{"class":944},"Date",[743,1075,228],{"class":749},[743,1077,1078],{"class":951},"now",[743,1080,1081],{"class":1038},"() ",[743,1083,1084],{"class":749},"\u002F",[743,1086,1088],{"class":1087},"sbssI"," 1000",[743,1090,965],{"class":1038},[743,1092,228],{"class":749},[743,1094,1095],{"class":951},"toString",[743,1097,1098],{"class":1038},"()",[743,1100,968],{"class":749},[743,1102,1103,1105,1108,1110,1113,1115,1118,1120,1122,1125,1127,1129,1131,1134,1136,1139,1141,1143,1146,1148,1150,1153,1155,1157],{"class":745,"line":843},[743,1104,1021],{"class":759},[743,1106,1107],{"class":944}," bodyHash",[743,1109,1027],{"class":749},[743,1111,1112],{"class":944}," crypto",[743,1114,228],{"class":749},[743,1116,1117],{"class":951},"createHash",[743,1119,955],{"class":1038},[743,1121,763],{"class":749},[743,1123,1124],{"class":788},"sha256",[743,1126,763],{"class":749},[743,1128,965],{"class":1038},[743,1130,228],{"class":749},[743,1132,1133],{"class":951},"update",[743,1135,955],{"class":1038},[743,1137,1138],{"class":944},"raw",[743,1140,965],{"class":1038},[743,1142,228],{"class":749},[743,1144,1145],{"class":951},"digest",[743,1147,955],{"class":1038},[743,1149,763],{"class":749},[743,1151,1152],{"class":788},"hex",[743,1154,763],{"class":749},[743,1156,965],{"class":1038},[743,1158,968],{"class":749},[743,1160,1162,1164,1167,1169,1172,1175,1178,1180,1183,1186,1188,1190,1192,1195,1197,1199,1201,1204,1207],{"class":745,"line":1161},8,[743,1163,1021],{"class":759},[743,1165,1166],{"class":944}," canonical",[743,1168,1027],{"class":749},[743,1170,1171],{"class":749}," `${",[743,1173,1174],{"class":944},"method",[743,1176,1177],{"class":749},"}",[743,1179,447],{"class":944},[743,1181,1182],{"class":749},"${",[743,1184,1185],{"class":944},"target",[743,1187,1177],{"class":749},[743,1189,447],{"class":944},[743,1191,1182],{"class":749},[743,1193,1194],{"class":944},"ts",[743,1196,1177],{"class":749},[743,1198,447],{"class":944},[743,1200,1182],{"class":749},[743,1202,1203],{"class":944},"bodyHash",[743,1205,1206],{"class":749},"}`",[743,1208,968],{"class":749},[743,1210,1212,1214,1217,1219],{"class":745,"line":1211},9,[743,1213,1021],{"class":759},[743,1215,1216],{"class":944}," signature",[743,1218,1027],{"class":749},[743,1220,1221],{"class":944}," crypto\n",[743,1223,1225,1228,1231,1233,1235,1237,1239,1241,1243],{"class":745,"line":1224},10,[743,1226,1227],{"class":749},"    .",[743,1229,1230],{"class":951},"createHmac",[743,1232,955],{"class":1038},[743,1234,763],{"class":749},[743,1236,1124],{"class":788},[743,1238,763],{"class":749},[743,1240,992],{"class":749},[743,1242,989],{"class":944},[743,1244,1245],{"class":1038},")\n",[743,1247,1249,1251,1253,1255,1258],{"class":745,"line":1248},11,[743,1250,1227],{"class":749},[743,1252,1133],{"class":951},[743,1254,955],{"class":1038},[743,1256,1257],{"class":944},"canonical",[743,1259,1245],{"class":1038},[743,1261,1263,1265,1267,1269,1271,1273,1275,1277],{"class":745,"line":1262},12,[743,1264,1227],{"class":749},[743,1266,1145],{"class":951},[743,1268,955],{"class":1038},[743,1270,763],{"class":749},[743,1272,1152],{"class":788},[743,1274,763],{"class":749},[743,1276,965],{"class":1038},[743,1278,968],{"class":749},[743,1280,1282,1286,1289,1291,1293,1295],{"class":745,"line":1281},13,[743,1283,1285],{"class":1284},"s7zQu","  return",[743,1287,1288],{"class":749}," {",[743,1290,1058],{"class":944},[743,1292,992],{"class":749},[743,1294,1216],{"class":944},[743,1296,1297],{"class":749}," };\n",[743,1299,1301],{"class":745,"line":1300},14,[743,1302,846],{"class":749},[743,1304,1306],{"class":745,"line":1305},15,[743,1307,974],{"emptyLinePlaceholder":973},[743,1309,1311],{"class":745,"line":1310},16,[743,1312,1313],{"class":1015},"\u002F\u002F Example usage\n",[743,1315,1317,1319,1322,1324,1326,1329,1331],{"class":745,"line":1316},17,[743,1318,941],{"class":759},[743,1320,1321],{"class":944}," secret ",[743,1323,948],{"class":749},[743,1325,785],{"class":749},[743,1327,1328],{"class":788},"\u003C\u003CYOUR_SECRET>>",[743,1330,763],{"class":749},[743,1332,968],{"class":749},[743,1334,1336,1338,1341,1343,1346,1348,1351,1353,1356,1359,1361,1363,1366,1368,1371,1373,1376],{"class":745,"line":1335},18,[743,1337,941],{"class":759},[743,1339,1340],{"class":944}," body ",[743,1342,948],{"class":749},[743,1344,1345],{"class":944}," JSON",[743,1347,228],{"class":749},[743,1349,1350],{"class":951},"stringify",[743,1352,955],{"class":944},[743,1354,1355],{"class":749},"{",[743,1357,1358],{"class":1038}," amount",[743,1360,766],{"class":749},[743,1362,785],{"class":749},[743,1364,1365],{"class":788},"100.50",[743,1367,763],{"class":749},[743,1369,1370],{"class":749}," }",[743,1372,965],{"class":944},[743,1374,1375],{"class":749},";",[743,1377,1378],{"class":1015}," \u002F\u002F money = baht string!\n",[743,1380,1382,1384,1386,1388,1390,1393,1395,1397,1399,1401],{"class":745,"line":1381},19,[743,1383,941],{"class":759},[743,1385,1288],{"class":749},[743,1387,1058],{"class":944},[743,1389,992],{"class":749},[743,1391,1392],{"class":944}," signature ",[743,1394,1177],{"class":749},[743,1396,1027],{"class":749},[743,1398,982],{"class":951},[743,1400,955],{"class":944},[743,1402,750],{"class":749},[743,1404,1406,1409],{"class":745,"line":1405},20,[743,1407,1408],{"class":944},"  secret",[743,1410,793],{"class":749},[743,1412,1414,1417,1419,1421,1423,1425],{"class":745,"line":1413},21,[743,1415,1416],{"class":1038},"  method",[743,1418,766],{"class":749},[743,1420,785],{"class":749},[743,1422,490],{"class":788},[743,1424,763],{"class":749},[743,1426,793],{"class":749},[743,1428,1430,1433,1435,1437,1439,1441],{"class":745,"line":1429},22,[743,1431,1432],{"class":1038},"  target",[743,1434,766],{"class":749},[743,1436,785],{"class":749},[743,1438,511],{"class":788},[743,1440,763],{"class":749},[743,1442,793],{"class":749},[743,1444,1446,1449],{"class":745,"line":1445},23,[743,1447,1448],{"class":944},"  body",[743,1450,793],{"class":749},[743,1452,1454,1456,1458],{"class":745,"line":1453},24,[743,1455,1177],{"class":749},[743,1457,965],{"class":944},[743,1459,968],{"class":749},[743,1461,1463],{"class":745,"line":1462},25,[743,1464,1465],{"class":1015},"\u002F\u002F Send: X-Api-Key, X-Signature=signature, X-Timestamp=ts, body=body (same bytes)\n",[451,1467,1472],{"className":1468,"code":1469,"filename":1470,"language":1471,"meta":459,"style":459},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import hashlib, hmac, time\n\ndef sign_request(secret: str, method: str, target: str, body: bytes):\n    ts = str(int(time.time()))\n    body_hash = hashlib.sha256(body).hexdigest()      # GET: body = b\"\"\n    canonical = f\"{method}\\n{target}\\n{ts}\\n{body_hash}\"\n    signature = hmac.new(secret.encode(), canonical.encode(), hashlib.sha256).hexdigest()\n    return ts, signature\n\nsecret = \"\u003C\u003CYOUR_SECRET>>\"\nbody = b'{\"amount\":\"100.50\"}'                          # the same bytes you send\nts, sig = sign_request(secret, \"POST\", \"\u002Fv1\u002Fdeposits\", body)\n","Python","python",[204,1473,1474,1492,1496,1541,1567,1594,1639,1686,1698,1702,1715,1736],{"__ignoreMap":459},[743,1475,1476,1479,1482,1484,1487,1489],{"class":745,"line":746},[743,1477,1478],{"class":1284},"import",[743,1480,1481],{"class":944}," hashlib",[743,1483,992],{"class":749},[743,1485,1486],{"class":944}," hmac",[743,1488,992],{"class":749},[743,1490,1491],{"class":944}," time\n",[743,1493,1494],{"class":745,"line":753},[743,1495,974],{"emptyLinePlaceholder":973},[743,1497,1498,1501,1504,1506,1508,1510,1513,1515,1517,1519,1521,1523,1525,1527,1529,1531,1533,1535,1538],{"class":745,"line":772},[743,1499,1500],{"class":759},"def",[743,1502,1503],{"class":951}," sign_request",[743,1505,955],{"class":749},[743,1507,279],{"class":988},[743,1509,766],{"class":749},[743,1511,1512],{"class":778}," str",[743,1514,992],{"class":749},[743,1516,995],{"class":988},[743,1518,766],{"class":749},[743,1520,1512],{"class":778},[743,1522,992],{"class":749},[743,1524,1000],{"class":988},[743,1526,766],{"class":749},[743,1528,1512],{"class":778},[743,1530,992],{"class":749},[743,1532,1005],{"class":988},[743,1534,766],{"class":749},[743,1536,1537],{"class":778}," bytes",[743,1539,1540],{"class":749},"):\n",[743,1542,1543,1546,1548,1550,1552,1555,1557,1560,1562,1564],{"class":745,"line":796},[743,1544,1545],{"class":944},"    ts ",[743,1547,948],{"class":749},[743,1549,1512],{"class":778},[743,1551,955],{"class":749},[743,1553,1554],{"class":778},"int",[743,1556,955],{"class":749},[743,1558,1559],{"class":951},"time",[743,1561,228],{"class":749},[743,1563,1559],{"class":951},[743,1565,1566],{"class":749},"()))\n",[743,1568,1569,1572,1574,1576,1578,1580,1582,1584,1586,1589,1591],{"class":745,"line":817},[743,1570,1571],{"class":944},"    body_hash ",[743,1573,948],{"class":749},[743,1575,1481],{"class":944},[743,1577,228],{"class":749},[743,1579,1124],{"class":951},[743,1581,955],{"class":749},[743,1583,1041],{"class":951},[743,1585,264],{"class":749},[743,1587,1588],{"class":951},"hexdigest",[743,1590,1098],{"class":749},[743,1592,1593],{"class":1015},"      # GET: body = b\"\"\n",[743,1595,1596,1599,1601,1604,1606,1608,1610,1612,1614,1616,1618,1620,1622,1624,1626,1628,1630,1632,1635,1637],{"class":745,"line":837},[743,1597,1598],{"class":944},"    canonical ",[743,1600,948],{"class":749},[743,1602,1603],{"class":759}," f",[743,1605,763],{"class":788},[743,1607,1355],{"class":1087},[743,1609,1174],{"class":944},[743,1611,1177],{"class":1087},[743,1613,447],{"class":944},[743,1615,1355],{"class":1087},[743,1617,1185],{"class":944},[743,1619,1177],{"class":1087},[743,1621,447],{"class":944},[743,1623,1355],{"class":1087},[743,1625,1194],{"class":944},[743,1627,1177],{"class":1087},[743,1629,447],{"class":944},[743,1631,1355],{"class":1087},[743,1633,1634],{"class":944},"body_hash",[743,1636,1177],{"class":1087},[743,1638,834],{"class":788},[743,1640,1641,1644,1646,1648,1650,1653,1655,1657,1659,1662,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683],{"class":745,"line":843},[743,1642,1643],{"class":944},"    signature ",[743,1645,948],{"class":749},[743,1647,1486],{"class":944},[743,1649,228],{"class":749},[743,1651,1652],{"class":951},"new",[743,1654,955],{"class":749},[743,1656,279],{"class":951},[743,1658,228],{"class":749},[743,1660,1661],{"class":951},"encode",[743,1663,1664],{"class":749},"(),",[743,1666,1166],{"class":951},[743,1668,228],{"class":749},[743,1670,1661],{"class":951},[743,1672,1664],{"class":749},[743,1674,1481],{"class":951},[743,1676,228],{"class":749},[743,1678,1124],{"class":1038},[743,1680,264],{"class":749},[743,1682,1588],{"class":951},[743,1684,1685],{"class":749},"()\n",[743,1687,1688,1691,1693,1695],{"class":745,"line":1161},[743,1689,1690],{"class":1284},"    return",[743,1692,1058],{"class":944},[743,1694,992],{"class":749},[743,1696,1697],{"class":944}," signature\n",[743,1699,1700],{"class":745,"line":1211},[743,1701,974],{"emptyLinePlaceholder":973},[743,1703,1704,1707,1709,1711,1713],{"class":745,"line":1224},[743,1705,1706],{"class":944},"secret ",[743,1708,948],{"class":749},[743,1710,785],{"class":749},[743,1712,1328],{"class":788},[743,1714,834],{"class":749},[743,1716,1717,1720,1722,1725,1728,1731,1733],{"class":745,"line":1248},[743,1718,1719],{"class":944},"body ",[743,1721,948],{"class":749},[743,1723,1724],{"class":759}," b",[743,1726,1727],{"class":749},"'",[743,1729,1730],{"class":788},"{\"amount\":\"100.50\"}",[743,1732,1727],{"class":749},[743,1734,1735],{"class":1015},"                          # the same bytes you send\n",[743,1737,1738,1740,1742,1745,1747,1749,1751,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771,1773],{"class":745,"line":1262},[743,1739,1194],{"class":944},[743,1741,992],{"class":749},[743,1743,1744],{"class":944}," sig ",[743,1746,948],{"class":749},[743,1748,1503],{"class":951},[743,1750,955],{"class":749},[743,1752,279],{"class":951},[743,1754,992],{"class":749},[743,1756,785],{"class":749},[743,1758,490],{"class":788},[743,1760,763],{"class":749},[743,1762,992],{"class":749},[743,1764,785],{"class":749},[743,1766,511],{"class":788},[743,1768,763],{"class":749},[743,1770,992],{"class":749},[743,1772,1005],{"class":951},[743,1774,1245],{"class":749},[451,1776,1781],{"className":1777,"code":1778,"filename":1779,"language":1780,"meta":459,"style":459},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","SECRET=\"\u003C\u003CYOUR_SECRET>>\"\nKEY_ID=\"unk_live_xxxxxxxxxxxx\"\nMETHOD=\"POST\"\nTARGET=\"\u002Fv1\u002Fdeposits\"\nBODY='{\"amount\":\"100.50\"}'   # money = baht string with 2 decimals\n\nTS=$(date +%s)\nBODY_HASH=$(printf '%s' \"$BODY\" | openssl dgst -sha256 -hex | awk '{print $NF}')\nCANONICAL=$(printf '%s\\n%s\\n%s\\n%s' \"$METHOD\" \"$TARGET\" \"$TS\" \"$BODY_HASH\")\nSIG=$(printf '%s' \"$CANONICAL\" | openssl dgst -sha256 -hmac \"$SECRET\" -hex | awk '{print $NF}')\n\ncurl -X \"$METHOD\" \"https:\u002F\u002Fapi.unkpay.co${TARGET}\" \\\n  -H \"X-Api-Key: ${KEY_ID}\" \\\n  -H \"X-Signature: ${SIG}\" \\\n  -H \"X-Timestamp: ${TS}\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  --data-raw \"$BODY\"\n","bash \u002F openssl + curl","bash",[204,1782,1783,1796,1810,1823,1836,1852,1856,1872,1926,1972,2026,2030,2059,2077,2094,2111,2124],{"__ignoreMap":459},[743,1784,1785,1788,1790,1792,1794],{"class":745,"line":746},[743,1786,1787],{"class":944},"SECRET",[743,1789,948],{"class":749},[743,1791,763],{"class":749},[743,1793,1328],{"class":788},[743,1795,834],{"class":749},[743,1797,1798,1801,1803,1805,1808],{"class":745,"line":753},[743,1799,1800],{"class":944},"KEY_ID",[743,1802,948],{"class":749},[743,1804,763],{"class":749},[743,1806,1807],{"class":788},"unk_live_xxxxxxxxxxxx",[743,1809,834],{"class":749},[743,1811,1812,1815,1817,1819,1821],{"class":745,"line":772},[743,1813,1814],{"class":944},"METHOD",[743,1816,948],{"class":749},[743,1818,763],{"class":749},[743,1820,490],{"class":788},[743,1822,834],{"class":749},[743,1824,1825,1828,1830,1832,1834],{"class":745,"line":796},[743,1826,1827],{"class":944},"TARGET",[743,1829,948],{"class":749},[743,1831,763],{"class":749},[743,1833,511],{"class":788},[743,1835,834],{"class":749},[743,1837,1838,1841,1843,1845,1847,1849],{"class":745,"line":817},[743,1839,1840],{"class":944},"BODY",[743,1842,948],{"class":749},[743,1844,1727],{"class":749},[743,1846,1730],{"class":788},[743,1848,1727],{"class":749},[743,1850,1851],{"class":1015},"   # money = baht string with 2 decimals\n",[743,1853,1854],{"class":745,"line":837},[743,1855,974],{"emptyLinePlaceholder":973},[743,1857,1858,1861,1864,1867,1870],{"class":745,"line":843},[743,1859,1860],{"class":944},"TS",[743,1862,1863],{"class":749},"=$(",[743,1865,1866],{"class":778},"date",[743,1868,1869],{"class":788}," +%s",[743,1871,1245],{"class":749},[743,1873,1874,1877,1879,1882,1885,1888,1890,1892,1895,1897,1900,1903,1906,1909,1912,1914,1917,1919,1922,1924],{"class":745,"line":1161},[743,1875,1876],{"class":944},"BODY_HASH",[743,1878,1863],{"class":749},[743,1880,1881],{"class":951},"printf",[743,1883,1884],{"class":749}," '",[743,1886,1887],{"class":788},"%s",[743,1889,1727],{"class":749},[743,1891,785],{"class":749},[743,1893,1894],{"class":944},"$BODY",[743,1896,763],{"class":749},[743,1898,1899],{"class":749}," |",[743,1901,1902],{"class":778}," openssl",[743,1904,1905],{"class":788}," dgst",[743,1907,1908],{"class":788}," -sha256",[743,1910,1911],{"class":788}," -hex",[743,1913,1899],{"class":749},[743,1915,1916],{"class":778}," awk",[743,1918,1884],{"class":749},[743,1920,1921],{"class":788},"{print $NF}",[743,1923,1727],{"class":749},[743,1925,1245],{"class":749},[743,1927,1928,1931,1933,1935,1937,1940,1942,1944,1947,1949,1951,1954,1956,1958,1961,1963,1965,1968,1970],{"class":745,"line":1211},[743,1929,1930],{"class":944},"CANONICAL",[743,1932,1863],{"class":749},[743,1934,1881],{"class":951},[743,1936,1884],{"class":749},[743,1938,1939],{"class":788},"%s\\n%s\\n%s\\n%s",[743,1941,1727],{"class":749},[743,1943,785],{"class":749},[743,1945,1946],{"class":944},"$METHOD",[743,1948,763],{"class":749},[743,1950,785],{"class":749},[743,1952,1953],{"class":944},"$TARGET",[743,1955,763],{"class":749},[743,1957,785],{"class":749},[743,1959,1960],{"class":944},"$TS",[743,1962,763],{"class":749},[743,1964,785],{"class":749},[743,1966,1967],{"class":944},"$BODY_HASH",[743,1969,763],{"class":749},[743,1971,1245],{"class":749},[743,1973,1974,1977,1979,1981,1983,1985,1987,1989,1992,1994,1996,1998,2000,2002,2005,2007,2010,2012,2014,2016,2018,2020,2022,2024],{"class":745,"line":1224},[743,1975,1976],{"class":944},"SIG",[743,1978,1863],{"class":749},[743,1980,1881],{"class":951},[743,1982,1884],{"class":749},[743,1984,1887],{"class":788},[743,1986,1727],{"class":749},[743,1988,785],{"class":749},[743,1990,1991],{"class":944},"$CANONICAL",[743,1993,763],{"class":749},[743,1995,1899],{"class":749},[743,1997,1902],{"class":778},[743,1999,1905],{"class":788},[743,2001,1908],{"class":788},[743,2003,2004],{"class":788}," -hmac",[743,2006,785],{"class":749},[743,2008,2009],{"class":944},"$SECRET",[743,2011,763],{"class":749},[743,2013,1911],{"class":788},[743,2015,1899],{"class":749},[743,2017,1916],{"class":778},[743,2019,1884],{"class":749},[743,2021,1921],{"class":788},[743,2023,1727],{"class":749},[743,2025,1245],{"class":749},[743,2027,2028],{"class":745,"line":1248},[743,2029,974],{"emptyLinePlaceholder":973},[743,2031,2032,2035,2038,2040,2042,2044,2046,2049,2051,2053,2056],{"class":745,"line":1262},[743,2033,2034],{"class":778},"curl",[743,2036,2037],{"class":788}," -X",[743,2039,785],{"class":749},[743,2041,1946],{"class":944},[743,2043,763],{"class":749},[743,2045,785],{"class":749},[743,2047,2048],{"class":788},"https:\u002F\u002Fapi.unkpay.co",[743,2050,1182],{"class":749},[743,2052,1827],{"class":944},[743,2054,2055],{"class":749},"}\"",[743,2057,2058],{"class":944}," \\\n",[743,2060,2061,2064,2066,2069,2071,2073,2075],{"class":745,"line":1281},[743,2062,2063],{"class":788},"  -H",[743,2065,785],{"class":749},[743,2067,2068],{"class":788},"X-Api-Key: ",[743,2070,1182],{"class":749},[743,2072,1800],{"class":944},[743,2074,2055],{"class":749},[743,2076,2058],{"class":944},[743,2078,2079,2081,2083,2086,2088,2090,2092],{"class":745,"line":1300},[743,2080,2063],{"class":788},[743,2082,785],{"class":749},[743,2084,2085],{"class":788},"X-Signature: ",[743,2087,1182],{"class":749},[743,2089,1976],{"class":944},[743,2091,2055],{"class":749},[743,2093,2058],{"class":944},[743,2095,2096,2098,2100,2103,2105,2107,2109],{"class":745,"line":1305},[743,2097,2063],{"class":788},[743,2099,785],{"class":749},[743,2101,2102],{"class":788},"X-Timestamp: ",[743,2104,1182],{"class":749},[743,2106,1860],{"class":944},[743,2108,2055],{"class":749},[743,2110,2058],{"class":944},[743,2112,2113,2115,2117,2120,2122],{"class":745,"line":1310},[743,2114,2063],{"class":788},[743,2116,785],{"class":749},[743,2118,2119],{"class":788},"Content-Type: application\u002Fjson",[743,2121,763],{"class":749},[743,2123,2058],{"class":944},[743,2125,2126,2129,2131,2133],{"class":745,"line":1316},[743,2127,2128],{"class":788},"  --data-raw",[743,2130,785],{"class":749},[743,2132,1894],{"class":944},[743,2134,834],{"class":749},[2136,2137,2138],"caution",{},[200,2139,2140,2141,2144,2145,2148,2149,2152],{},"In bash you must send the body with ",[204,2142,2143],{},"--data-raw"," (not ",[204,2146,2147],{},"-d",", which may strip newlines) and you must hash the ",[209,2150,2151],{},"same bytes curl actually sends"," — if the body has a different newline or whitespace, the hash will not match.",[432,2154],{"value":2155},"confirm the real path of the first endpoint a merchant will call (the code has POST \u002Fv1\u002Fdeposits, GET \u002Fv1\u002Fdeposits\u002F:id, POST \u002Fv1\u002Fdeposits\u002F:id\u002Fcancel) and the body fields of POST \u002Fv1\u002Fdeposits",[2157,2158,2159],"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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .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 .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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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}",{"title":459,"searchDepth":746,"depth":753,"links":2161},[2162,2163,2164,2165,2166,2167],{"id":268,"depth":753,"text":269},{"id":437,"depth":753,"text":438},{"id":609,"depth":753,"text":610},{"id":675,"depth":753,"text":676},{"id":877,"depth":753,"text":878},{"id":917,"depth":753,"text":918},"Every S2S request is signed with HMAC-SHA256 using your API key id and secret — a bare API key is never accepted","md",{},{"icon":30},{"title":27,"description":2168},"CLRl1hBe5XGPJpt-I6IgF2Eq8JG1lsQ0LFQTCGz6nZg",[2175,2177],{"title":16,"path":17,"stem":18,"description":2176,"icon":19,"children":-1},"Make your first end-to-end deposit in the sandbox with a test key",{"title":32,"path":33,"stem":34,"description":2178,"icon":35,"children":-1},"An IP allowlist on the s2s surface layers on top of HMAC — blocked source IPs get 403 IP_NOT_ALLOWED",1781891152608]