[{"data":1,"prerenderedAt":650},["ShallowReactive",2],{"navigation-en":3,"en:\u002Fdeposits\u002Foverview":193,"en:\u002Fdeposits\u002Foverview:surround":645},[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":58,"badge":195,"body":196,"description":639,"extension":640,"links":195,"meta":641,"method":195,"navigation":642,"path":59,"seo":643,"stem":60,"__hash__":644},"docs_en\u002F3.deposits\u002F1.overview.md",null,{"type":197,"value":198,"toc":629},"minimark",[199,203,233,237,242,303,325,338,342,346,356,430,440,444,454,473,498,502,536,543,546,550,578,582],[200,201,202],"p",{},"This section explains how a merchant takes money in from a customer through UnknownPay Server-to-Server (S2S): from \"create a deposit\" → \"let the customer transfer\" → \"the system matches and credits the balance\" through \"track status\" and \"cancel\".",[204,205,206],"warning",{},[200,207,208,212,213,216,217,221,222,225,226,225,229,232],{},[209,210,211],"strong",{},"Money reminder (very important):"," every money field on the wire is a ",[209,214,215],{},"baht string with 2 decimals",", e.g. ",[218,219,220],"code",{},"\"100.50\""," — not a JSON number and not satang. Fields such as ",[218,223,224],{},"amount",", ",[218,227,228],{},"expected_amount",[218,230,231],{},"matched_amount"," must always be sent\u002Fread as strings.",[234,235],"placeholder-image",{"subject":236},"sequence diagram — Merchant → POST \u002Fv1\u002Fdeposits → returns expected_amount + QR → customer transfers the exact amount → bank feed → matcher → deposit CREDITED → merchant balance increases",[238,239,241],"h2",{"id":240},"related-endpoints","Related endpoints",[243,244,245,261],"table",{},[246,247,248],"thead",{},[249,250,251,255,258],"tr",{},[252,253,254],"th",{},"Operation",[252,256,257],{},"Method + Path",[252,259,260],{},"Auth",[262,263,264,278,291],"tbody",{},[249,265,266,270,275],{},[267,268,269],"td",{},"Create a deposit",[267,271,272],{},[218,273,274],{},"POST \u002Fv1\u002Fdeposits",[267,276,277],{},"S2S (HMAC) + Idempotency-Key",[249,279,280,283,288],{},[267,281,282],{},"Get \u002F retrieve a deposit",[267,284,285],{},[218,286,287],{},"GET \u002Fv1\u002Fdeposits\u002F:id",[267,289,290],{},"S2S (HMAC)",[249,292,293,296,301],{},[267,294,295],{},"Cancel a deposit",[267,297,298],{},[218,299,300],{},"POST \u002Fv1\u002Fdeposits\u002F:id\u002Fcancel",[267,302,290],{},[200,304,305,306,312,313,316,317,320,321,324],{},"All three endpoints sit on the ",[209,307,308,309],{},"gateway surface ",[218,310,311],{},"\u002Fv1"," and must be HMAC-signed on every call (see ",[314,315,27],"a",{"href":28},"). The system derives ",[218,318,319],{},"merchant"," and ",[218,322,323],{},"mode"," (live\u002Ftest) from the signing API key itself — you never send a merchant id in the body.",[326,327,328],"note",{},[200,329,330,331,333,334,337],{},"These paths are also the paths the HMAC signature matches against. The system is mounted under the ",[218,332,311],{}," prefix, so the full path is ",[218,335,336],{},"\u002Fv1\u002Fdeposits"," and so on.",[339,340],"placeholder-note",{"value":341},"confirm the gateway router prefix is \u002Fv1 and matches production ingress",[238,343,345],{"id":344},"state-machine","State machine",[347,348,354],"pre",{"className":349,"code":351,"language":352,"meta":353},[350],"language-text","                 ┌───────────────┐\n                 │    PENDING    │  (initial status after creation)\n                 └───────┬───────┘\n        ┌────────────────┼─────────────────────┐\n   customer transfers     past match_window      merchant\u002Fsystem cancels\n   exact expected_amount         │                       │\n        ▼                       ▼                       ▼\n   ┌───────────┐          ┌───────────┐          ┌─────────────┐\n   │ CREDITED  │          │  EXPIRED  │          │  CANCELLED  │\n   └───────────┘          └───────────┘          └─────────────┘\n     (terminal)             (terminal)             (terminal)\n","text","",[218,355,351],{"__ignoreMap":353},[243,357,358,368],{},[246,359,360],{},[249,361,362,365],{},[252,363,364],{},"Status",[252,366,367],{},"Meaning",[262,369,370,383,399,415],{},[249,371,372,377],{},[267,373,374],{},[218,375,376],{},"PENDING",[267,378,379,380,382],{},"Created; waiting for the customer to transfer the exact ",[218,381,228],{}," within the time window.",[249,384,385,390],{},[267,386,387],{},[218,388,389],{},"CREDITED",[267,391,392,393,395,396],{},"Inbound money matched — credited to the merchant balance (",[218,394,231],{}," = the amount actually received). ",[209,397,398],{},"terminal",[249,400,401,406],{},[267,402,403],{},[218,404,405],{},"EXPIRED",[267,407,408,409,412,413],{},"The ",[218,410,411],{},"match_window"," elapsed with no matching inbound amount → expired. ",[209,414,398],{},[249,416,417,422],{},[267,418,419],{},[218,420,421],{},"CANCELLED",[267,423,424,425,427,428],{},"Cancelled while still ",[218,426,376],{},". ",[209,429,398],{},[200,431,432,433,436,437,439],{},"A deposit is ",[209,434,435],{},"single-phase"," (no intermediate state): from ",[218,438,376],{}," it ends in exactly 1 of the 3 terminals, and once terminal it cannot change back.",[238,441,443],{"id":442},"exact-amount-matching","Exact-amount matching",[200,445,446,447,453],{},"The system matches inbound money with a simple rule: ",[209,448,449,450,452],{},"the amount arriving in the account must equal ",[218,451,228],{}," exactly",", so it can tell which inbound payment belongs to which deposit (many customers may transfer into the same pool account at nearly the same time).",[200,455,456,457,459,460,463,464,216,467,459,469,472],{},"So when a merchant requests ",[218,458,224],{}," = ",[218,461,462],{},"\"500.00\"",", the system ",[209,465,466],{},"adds a small satang remainder to make a value unique among other outstanding deposits",[218,468,228],{},[218,470,471],{},"\"500.37\"",". This is the deposit's \"signature amount\".",[474,475,476],"caution",{},[200,477,478,479,484,485,487,488,491,492,494,495,497],{},"The customer ",[209,480,481,482],{},"must transfer the exact ",[218,483,228],{}," (not ",[218,486,224],{},") for the system to match and credit it. For PROMPTPAY_QR the amount is embedded in ",[218,489,490],{},"qr_payload"," automatically; for BANK_TRANSFER you must show ",[218,493,228],{}," clearly and remind the customer to enter it down to the satang. If the customer transfers the wrong amount, the deposit may not match and will expire as ",[218,496,405],{},".",[238,499,501],{"id":500},"timing-ttl-grace","Timing (TTL + grace)",[503,504,505,516,528],"ul",{},[506,507,508,511,512,515],"li",{},[218,509,510],{},"display_expires_at"," = the QR \u002F payment-page display time = creation time ",[209,513,514],{},"+ 5 minutes"," (display TTL).",[506,517,518,459,521,523,524,527],{},[218,519,520],{},"match_window_until",[218,522,510],{}," ",[209,525,526],{},"+ 2 minutes"," (grace) = the last moment the system will still match an inbound amount.",[506,529,530,531,533,534,497],{},"Once ",[218,532,520],{}," passes with no matching inbound amount, the deposit is swept to ",[218,535,405],{},[200,537,538,539,542],{},"So the total window in which the customer should finish transferring is ",[209,540,541],{},"within ~5 minutes"," (plus a 2-minute grace for a slow bank feed, ~7 minutes total).",[339,544],{"value":545},"confirm the display TTL (5 minutes) and grace (2 minutes) match current production config",[238,547,549],{"id":548},"outcome-arrives-via-webhook","Outcome arrives via webhook",[474,551,552],{},[200,553,554,557,558,561,562,320,564,561,567,569,570,523,573,575,576,497],{},[209,555,556],{},"The final deposit result arrives via Webhook."," The system fires ",[218,559,560],{},"deposit.success"," on ",[218,563,389],{},[218,565,566],{},"deposit.expired",[218,568,405],{},". Never treat a ",[218,571,572],{},"201",[218,574,376],{}," as final — wait for the terminal webhook. See payload structure and verification under ",[314,577,111],{"href":118},[238,579,581],{"id":580},"points-merchants-must-watch","Points merchants must watch",[583,584,585,594,607,617,623],"ol",{},[506,586,587,590,591,593],{},[209,588,589],{},"Every money field is a baht string"," (",[218,592,471],{},") — don't send\u002Fparse it as a number or satang.",[506,595,596,484,601,603,604,606],{},[209,597,598,599],{},"The customer must transfer the exact ",[218,600,228],{},[218,602,224],{},") for matching — use ",[218,605,490],{}," to make the amount correct automatically.",[506,608,609,616],{},[209,610,611,612,615],{},"Send an ",[218,613,614],{},"Idempotency-Key"," on every create"," to prevent duplicate deposits from retries.",[506,618,619,622],{},[209,620,621],{},"Send the full payer for both methods"," — used for anti-fraud checks.",[506,624,625,628],{},[209,626,627],{},"Deposits are short-lived (~5–7 minutes)"," — show the QR and let the customer transfer immediately; if it expires you must create a new one.",{"title":353,"searchDepth":630,"depth":631,"links":632},1,2,[633,634,635,636,637,638],{"id":240,"depth":631,"text":241},{"id":344,"depth":631,"text":345},{"id":442,"depth":631,"text":443},{"id":500,"depth":631,"text":501},{"id":548,"depth":631,"text":549},{"id":580,"depth":631,"text":581},"How a merchant takes money in via UnknownPay S2S — from creating a deposit to exact-amount matching, crediting, and the PENDING → CREDITED \u002F EXPIRED \u002F CANCELLED state machine","md",{},{"icon":61},{"title":58,"description":639},"jg_jXLBRXAyHMGwKcaL62jp9HrfILfmuVi_hBhhzk4k",[646,648],{"title":47,"path":48,"stem":49,"description":647,"icon":50,"children":-1},"Every error uses one JSON envelope — branch on error.code, never the message — plus the consolidated cross-cutting error reference",{"title":63,"path":64,"stem":65,"description":649,"icon":66,"children":-1},"POST \u002Fv1\u002Fdeposits — create a deposit with HMAC + Idempotency-Key; returns expected_amount and pay_to \u002F qr_payload with status PENDING",1781891152608]