[{"data":1,"prerenderedAt":552},["ShallowReactive",2],{"navigation-en":3,"en:\u002Fwebhooks\u002Fdelivery-and-retries":193,"en:\u002Fwebhooks\u002Fdelivery-and-retries:surround":547},[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":130,"badge":195,"body":196,"description":541,"extension":542,"links":195,"meta":543,"method":195,"navigation":544,"path":131,"seo":545,"stem":132,"__hash__":546},"docs_en\u002F6.webhooks\u002F4.delivery-and-retries.md",null,{"type":197,"value":198,"toc":533},"minimark",[199,204,211,256,271,275,400,429,433,440,515,529],[200,201,203],"h2",{"id":202},"merchant-endpoint-requirements","Merchant endpoint requirements",[205,206,207],"p",{},[208,209,210],"strong",{},"You must:",[212,213,214,225,232],"ul",{},[215,216,217,220,221,224],"li",{},[208,218,219],{},"Accept an HTTP POST"," at the URL you configured and return ",[208,222,223],{},"HTTP 2xx"," (200–299) on successful receipt — any other status counts as \"delivery failed\" and will be retried.",[215,226,227,228,231],{},"Respond quickly: our client has a ",[208,229,230],{},"total 10-second timeout"," per request (5-second connect timeout). Responding too slowly counts as a failure → retry. We recommend you ack 2xx immediately and process asynchronously.",[215,233,234,235,242,243,245,246,249,250,252,253,255],{},"Do ",[208,236,237,238],{},"idempotency with ",[239,240,241],"code",{},"event_id",": the ",[239,244,241],{}," (",[239,247,248],{},"\u003Cid>:\u003Cevent_type>",") is stable for one event throughout. Retries\u002Freplays send the same ",[239,251,241],{}," — if you have already processed it, return 2xx without doing the work again (e.g. store received ",[239,254,241],{},"s in your DB with a unique constraint).",[257,258,259],"caution",{},[205,260,261,267,268,270],{},[208,262,263,264,266],{},"Never trust a single delivery — process by ",[239,265,241],{}," idempotently."," Retries and replays re-send the same ",[239,269,241],{},"; if you have already handled it, return 2xx and do not re-apply the effect.",[200,272,274],{"id":273},"how-the-system-retries","How the system retries",[212,276,277,280,382,391],{},[215,278,279],{},"If you return non-2xx, time out, or are unreachable → the system retries with exponential backoff.",[215,281,282,283,286,287,371,374,375,377,378,381],{},"Maximum ",[208,284,285],{},"9 attempts"," (the first one + retries) per this backoff schedule:",[288,289,290,303],"table",{},[291,292,293],"thead",{},[294,295,296,300],"tr",{},[297,298,299],"th",{},"retry #",[297,301,302],{},"delay before re-sending",[304,305,306,315,323,331,339,347,355,363],"tbody",{},[294,307,308,312],{},[309,310,311],"td",{},"1",[309,313,314],{},"10 seconds",[294,316,317,320],{},[309,318,319],{},"2",[309,321,322],{},"1 minute",[294,324,325,328],{},[309,326,327],{},"3",[309,329,330],{},"5 minutes",[294,332,333,336],{},[309,334,335],{},"4",[309,337,338],{},"30 minutes",[294,340,341,344],{},[309,342,343],{},"5",[309,345,346],{},"2 hours",[294,348,349,352],{},[309,350,351],{},"6",[309,353,354],{},"6 hours",[294,356,357,360],{},[309,358,359],{},"7",[309,361,362],{},"12 hours",[294,364,365,368],{},[309,366,367],{},"8",[309,369,370],{},"24 hours",[372,373],"br",{},"The total retry window is roughly ",[208,376,370],{},". After that the event is considered terminal ",[239,379,380],{},"failed"," (it is logged).",[215,383,384,387,388,390],{},[208,385,386],{},"Circuit breaker:"," if your URL fails 5 times in a row, the system \"opens the breaker\" and temporarily stops sending to that URL for ",[208,389,322],{},", then tries again (to avoid hammering a downed endpoint) — this does not affect each event's 24-hour deadline.",[215,392,393,396,397,399],{},[208,394,395],{},"Replay:"," you can re-send the same event from the delivery log page in the Portal (the system enqueues a new delivery with the same ",[239,398,241],{},").",[205,401,402,403,405,406,405,409,245,412,415,416,415,419,421,422,405,425,428],{},"You can view the delivery history (delivery log) on the Webhook page in the Portal — filterable by status. Each record has: ",[239,404,241],{},", ",[239,407,408],{},"event_type",[239,410,411],{},"status",[239,413,414],{},"delivered"," \u002F ",[239,417,418],{},"retrying",[239,420,380],{},"), ",[239,423,424],{},"attempts",[239,426,427],{},"created_at"," (no payload, to prevent PII leaks).",[200,430,432],{"id":431},"url-requirements-https-ssrf","URL requirements (HTTPS + SSRF)",[205,434,435,436,439],{},"The destination URL must pass these conditions (checked at configuration time → returns ",[239,437,438],{},"422 INVALID_URL"," if it fails, and re-checked at real dial time as a backstop):",[212,441,442,456,512],{},[215,443,444,451,452,455],{},[208,445,446,447,450],{},"Must be ",[239,448,449],{},"https:\u002F\u002F"," only"," — ",[239,453,454],{},"http:\u002F\u002F"," is rejected, and redirects that downgrade to non-https are blocked.",[215,457,458,461,462],{},[208,459,460],{},"Must not point to internal\u002Fprivate addresses"," (SSRF protection) — hosts that resolve to these IPs are rejected:\n",[212,463,464,474,486,496,502],{},[215,465,466,467,405,470,473],{},"loopback (",[239,468,469],{},"127.0.0.1",[239,471,472],{},"::1",")",[215,475,476,477,405,480,405,483,473],{},"RFC1918 private (",[239,478,479],{},"10.0.0.0\u002F8",[239,481,482],{},"192.168.0.0\u002F16",[239,484,485],{},"172.16.0.0\u002F12",[215,487,488,489,492,493,473],{},"link-local \u002F cloud metadata (",[239,490,491],{},"169.254.0.0\u002F16",", e.g. ",[239,494,495],{},"169.254.169.254",[215,497,498,499,473],{},"carrier-grade NAT RFC 6598 (",[239,500,501],{},"100.64.0.0\u002F10",[215,503,504,505,508,509,473],{},"unspecified (",[239,506,507],{},"0.0.0.0",") and IPv6 ULA (",[239,510,511],{},"fc00::\u002F7",[215,513,514],{},"Redirects may be followed up to 5 hops, and every hop must be https.",[516,517,518],"warning",{},[205,519,520,521,524,525,528],{},"Your endpoint must therefore be a ",[208,522,523],{},"public host with TLS"," (a real domain + a valid certificate). You cannot use ",[239,526,527],{},"localhost",", an internal IP, or a tunnel that resolves to a private IP.",[530,531],"placeholder-note",{"value":532},"if you need to test locally, specify the recommended method (e.g. a public HTTPS tunnel that resolves to a public IP)",{"title":534,"searchDepth":535,"depth":536,"links":537},"",1,2,[538,539,540],{"id":202,"depth":536,"text":203},{"id":273,"depth":536,"text":274},{"id":431,"depth":536,"text":432},"What your webhook endpoint must do, the retry\u002Fbackoff schedule, replay, and the HTTPS\u002FSSRF rules that reject an INVALID_URL","md",{},{"icon":45},{"title":130,"description":541},"GzVHCCcUDHgUMS3UkLSIifaCfISRdmn1G4n0JKKdVrU",[548,550],{"title":126,"path":127,"stem":128,"description":549,"icon":35,"children":-1},"Verify the X-Webhook-Signature HMAC-SHA256 on the raw request bytes before parsing JSON, with Node.js and Python examples",{"title":140,"path":141,"stem":142,"description":551,"icon":61,"children":-1},"Sandbox \u002F Test Mode works Stripe-style — same business endpoints, signed with a test key, on a fully isolated test ledger",1781891157143]