Toss Payments: why the webhook, not the redirect, decides a sale
토스페이먼츠 연동 가이드: 결제 완료를 리다이렉트가 아닌 웹훅으로 처리해야 하는 이유
Foreign founders integrating Toss Payments often rely on the client browser redirect to grant access. That pattern breaks on mobile drops, tab closes, and virtual accounts. Toss Payments developer documentation mandates webhook-driven fulfillment. How the retry policy works, HMAC signature verification, and building idempotent handlers.

On this page
Korean payment gateways work differently from Stripe or PayPal checkout flows. When you integrate Toss Payments, the client browser widget executes user authentication and returns query parameters to your registered success URL.
Many engineering teams grant product entitlements immediately upon loading that success page. That design creates silent revenue losses and ghost orders.
Why browser redirects fail
A browser redirect depends entirely on client-side conditions. Three common scenarios prevent redirect-based fulfillment from executing:
| Scenario | Client redirect behavior | Webhook behavior |
|---|---|---|
| User closes browser after payment | Redirect never reaches your server | Server receives webhook event normally |
| Cellular connection drops | Browser shows connection error | Server receives webhook event directly |
| Virtual account (가상계좌) deposit | No browser redirect occurs at deposit time | Server receives deposit notification instantly |
| Query parameter manipulation | Tampered payment parameters reach endpoint | Cryptographic signature protects payload |
Virtual accounts highlight the flaw clearly. When a buyer selects a virtual account, Toss Payments issues account details. The customer pays hours later at an ATM or through banking apps.
Because the buyer is not browsing your site when depositing funds, no redirect can fire. Only an asynchronous webhook informs your system that money arrived.
The webhook delivery and retry mechanism
Toss Payments sends payment notifications via HTTP POST requests to your designated webhook endpoint. The payload contains complete payment details under the PAYMENT_STATUS_CHANGED event.
Your server must acknowledge receipt by returning an HTTP 200 status code. If your server returns an error or times out, Toss Payments assumes delivery failed.
| Delivery property | Toss Payments specification | Developer action |
|---|---|---|
| Target event | PAYMENT_STATUS_CHANGED | Filter on payment status (DONE, CANCELED) |
| Acknowledgment code | HTTP 200 OK | Return 200 before long-running tasks |
| Retry policy | Up to 7 attempts | Implement idempotent transaction handling |
| Security header | tosspayments-webhook-signature | Verify HMAC-SHA256 signature hash |
| Transmission tracking | tosspayments-webhook-transmission-id | Deduplicate incoming event IDs |
Toss Payments retries failed webhook deliveries up to 7 times with increasing time intervals. If your backend suffers temporary downtime, the gateway automatically replays undelivered events once your servers recover.
Implementing signature verification and idempotency
Because webhooks trigger database updates and inventory deductions, you must secure your webhook receiver against spoofing.
Toss Payments signs webhook payloads using HMAC-SHA256 with your API Secret Key. Your handler must recalculate the signature using the raw payload and transmission timestamp header, then compare hashes in constant time.
Network retries also mean your server may receive the identical webhook twice. Track the transmission ID in your database to ensure payment handlers run exactly once.
Founders scaling Korean ventures can review technical architectures and go-to-market strategies in our Ventures Workspace.
Related on KBridge: Korean data sent to a foreign AI API and the PSST plan format.
Frequently asked questions
- Can I fulfill customer orders using just the Toss Payments successUrl redirect?
- No. The successUrl redirect is a client-side navigation. If the user loses internet connection or closes their browser before the page loads, your server never receives the confirmation. Webhooks guarantee reliable delivery.
- What happens if my server fails to answer a Toss Payments webhook?
- If your server does not return an HTTP 200 response, Toss Payments considers the delivery failed and retries up to 7 times with increasing intervals.
- How do virtual accounts (가상계좌) work with redirects?
- Virtual accounts do not trigger redirects upon payment because the customer transfers money hours or days later from their bank. Only the PAYMENT_STATUS_CHANGED webhook notifies your system when the deposit clears.
- How should I handle duplicate webhook deliveries?
- Store the unique transmission ID provided in the webhook headers. Check this ID against your database to ensure your business logic processes each transaction only once.
- How do I secure the Toss Payments webhook endpoint?
- Verify the HMAC-SHA256 signature header sent with each webhook against your Toss Payments Secret Key. Reject any request where the calculated hash does not match.
- What HTTP status code must the webhook endpoint return?
- Your endpoint must return HTTP 200 OK. Returning any 4xx or 5xx code signals a delivery failure to Toss Payments, triggering its automatic retry loop.
Sources
Everything above is the rule as published. See how it applies to your case.
Read next
- FounderCraftSending Korean customer data to a foreign AI API: what PIPA Article 28-8 asks
- FounderCraftThe Business Model Canvas, mapped onto what a Korean 사업계획서 actually has to prove
- FounderCraftY Combinator's application and a Korean programme's: two processes, and what actually transfers
- FounderCraftValidate before the 모집공고 closes: what the printed calendar actually gives you