가이드/LLM Quick Reference
목차

링크 복사LLM Quick Reference

이 페이지는 AI 에이전트를 주 독자로 삼은 페이지예요. AI 도구에 컨텍스트로 첨부하거나 토스페이먼츠 MCP 서버와 함께 사용하세요. 본문은 토큰 효율을 위해 영어로 작성되어 있어요.

This page is optimized for AI agents: use it for routing and guardrails, then jump to the linked guide/reference for implementation details.

Page scope: flow model + decision rules + entry points + pitfalls + routing. Full code and details live in guide/reference pages.

Companion resource: When this page is insufficient, consult llms.txt first — the complete Toss Payments docs index in LLM-standard format. Use it to locate the precise guide/reference page for any topic not fully covered here.

Markdown source for any docs page: Append .md to any docs URL to fetch the raw markdown (more token-efficient than HTML; tabbed content is fully exposed). Examples: /reference.md, /guides/v2/payment-widget.md.

링크 복사AI Workflow

Recommended sequence when using this page:

  1. Read this page to build the mental model.
  2. Determine: SDK version → product → payment scenario.
  3. For details beyond this page, consult llms.txt → navigate to the precise guide/reference page.
  4. Generate implementation code.
  5. Validate against §8 Common Mistakes before finalizing.

링크 복사Decision defaults (when ambiguous)

  • Prefer V2 SDK unless the user specifies V1 or shows existing V1 code.
  • Prefer Payment Widget when no specific UI/scenario keyword is given.
  • Ask a brief clarification question only when ambiguity affects architecture (e.g., recurring vs one-time, custom UI vs default). Do not ask for cosmetic choices.

Server-authoritative model — Toss Payments follows this core principle:

  • Client may initiate payment authentication via the JS SDK.
  • Server must validate and finalize the payment state via the secret key (confirm API, billing API, refund API, webhook re-query).
  • Never trust client-provided payment state (amount, status, success). Always re-verify on the server.

This underlies amount verification (§2.2), confirm API (§5.A~C), billing flow (§5.D), and webhook handling (§7.2).

링크 복사1. Payment Flow Model

Toss Payments uses 3 actors: Client (browser) / Merchant Server / Toss Payments. The diagram below shows the basic flow for one-time payments (card, transfer, easy pay). Virtual account and auto-billing are variations of this flow.

In short:

  1. Client requests payment authentication via SDK → user authenticates at Toss Payments.
  2. Server confirms the authenticated payment with the secret key, then saves the result.

Responsibility split:

StepActorKey used
Payment request (requestPayment)Client (JS SDK)Client key
amount verificationMerchant server
Payment confirmation (/v1/payments/confirm)Merchant serverSecret key
Webhook handlingMerchant server

Scenario variations:

  • One-time payment (card / transfer / easy pay): Flow above as is.
  • Virtual account: Step 3 only issues an account number. Payment is finalized asynchronously via DEPOSIT_CALLBACK webhook after deposit.
  • Auto-billing: Billing key issuance (SDK method — variation of steps 2~4 / API method — server-only, separate contract required) → server calls billing endpoint for recurring payments.

링크 복사2. Critical

4 mandatory rules before integration. Violation leads to security incidents, payment tampering, or hallucinated code.

링크 복사2.1 Secret key is server-only, client key is browser-only

KeyPatternUsed in
Secret key(test|live)_sk_*Server
Client key(test|live)_ck_*Client (browser-exposed), SDK initialization

Never expose secret key — Including it in frontend code, GitHub pushes, or client responses leads to immediate security incidents.

For key types and issuance, see API Keys Guide.

링크 복사2.2 Mandatory server-side amount verification at confirmation

requestPayment runs in the client JS SDK, so a user can modify amount arbitrarily from the browser console. (e.g., the order shows 50,000 KRW but the console call is changed to amount: 100.) Authentication completes with the modified amount and the browser redirects via successUrl. If the merchant passes that value to the confirm API without verification, the payment completes at the tampered amount.

(Modifying the successUrl query string directly is blocked by the confirm API since it differs from the authenticated amount. The threat is tampering before authentication.)

Verify in the server that amount from successUrl matches the merchant's intended amount at request time before calling the Payment Confirmation API.

LLM authoring guideline — Even in toy/PoC code without a DB, leave a verification placeholder and inform the user via comment or response: "In production, must compare with server-stored amount."

링크 복사2.3 Authorization header is Basic base64(SECRET_KEY:)

Append a single colon to the secret key, then base64-encode. Missing colon is the most common mistake.

  • The password slot after the colon is empty (hence trailing colon).
  • If UTF-8 BOM is present, the result starts with 77u/. Re-encode without BOM.

For details, see Authorization Header.

링크 복사2.4 Do not invent fields

LLMs frequently hallucinate undocumented or deprecated fields when generating PG integration code. Use only fields defined in this page or in the linked SDK/API docs. If a field is not documented here or in linked docs, do not generate it.

  • Do not infer field names from other PG vendors (e.g., Stripe's payment_intent, KCP, INICIS).
  • Do not generate fields based on naming patterns alone (e.g., guessing payment_method_id when only method is documented).
  • If a needed field is unclear, consult llms.txt → exact page, or ask the user. Do not guess.

링크 복사3. Version Selection

  • V2 by default — If user does not specify V1, use V2.
  • Do not mix V1 and V2 — Common mistake: calling V2 methods on V1 SDK URL.
  • If existing code is V1, confirm with user before keeping V1.

Toss Payments SDK hierarchy:

SDK version is independent of API version — both V1 and V2 SDKs use api.tosspayments.com/v1/*.

ItemV1V2
JS SDK URLPer product (e.g., https://js.tosspayments.com/v1/payment-widget)Single (https://js.tosspayments.com/v2/standard)
SDK initPer product (PaymentWidget(), BrandPay(), TossPayments())One line TossPayments(clientKey), branched by methods

V2 SDK initialization and product methods:

For differences, see Migration Guide.

링크 복사4. Product Selection

링크 복사Decision rules

  1. If the user specifies a product, use it.
  2. If not specified, branch by user requirement keyword (table below).
  3. If no keyword matches, proceed with Payment Widget (default). Add a note at the end of the response: "If you want to build the payment method UI yourself, switch to Standard Payment Window."
  4. If keywords match two or more products, briefly confirm with the user.

링크 복사User requirement keywords → Product

KeywordProductV2 entry pointGuide
(Vague) "payment", "payment integration"Payment Widget (default)tossPayments.widgets()
"PG payment window", "fast integration"Standard Payment WindowtossPayments.payment()
"one-click", "password payment", "build own easy pay"BrandPaytossPayments.brandpay()
"subscription", "recurring", "billing"Auto-billingtossPayments.payment() (billing)
"seller settlement", "marketplace payout"PayoutsAPI direct (no SDK)

For full comparison, see Payment Products Comparison.

링크 복사Payment Widget vs Standard Payment Window (the most confusing branch)

The essence is who renders the payment method selection UI:

  • Payment Widget — SDK auto-renders. Merchant only provides a <div id="payment-methods" /> container.
  • Standard Payment Window — Merchant builds payment method selection UI directly → user-selected method passed to requestPayment({ method: "CARD" }). The variation where the merchant fully customizes the UI is Custom Payment Window (code pattern same as Standard).

If no specific clue, choose Payment Widget.

링크 복사5. Scenario Entry Points

Each scenario's V2 entry point, flow, and full-code routing. Look up full code in the guide pages — this page provides entry points only.

링크 복사Common identifiers

Used across all scenarios. Do not fill arbitrarily — follow format constraints.

IdentifierIssued byFormat
customerKeyMerchant2~300 chars. Letters, digits, and special chars (-, _, =, ., @). At least one special char required. UUID recommended. Do not use predictable values (email, phone, member ID). For non-members, ANONYMOUS is allowed.
orderIdMerchant6~64 chars. Letters, digits, -_. Unique per payment.
paymentKeyToss PaymentsReceived via successUrl after payment authentication. Payment identifier.
billingKeyToss PaymentsReceived after billing key issuance (scenario 5.D). Recurring payment token.

링크 복사Common types (anti-hallucination)

FieldV2 SDK callV1 SDK / Server API
amountObject: { value: integer, currency: "KRW" }Integer (e.g., 50000)
customerKey, orderId, orderNamestringstring
paymentKey, billingKeystringstring
Idempotency-Key (header)UUID v4 stringUUID v4 string

amount.value is always integer (no decimal in KRW). amount.currency is "KRW" (only KRW supported in V2 standard scope).

링크 복사Common — successUrl / failUrl handling

After client requestPayment, the auth result redirects to one of these URLs. Branch in merchant server.

  • successUrl query string (auth success): paymentKey, orderId, amount (Payment Widget also includes paymentType) → verify amount (Critical 2.2) → call confirm API.
  • failUrl query string (auth failure / user cancellation): code, message, orderIddo not call confirm API. Show a user-friendly message based on code, then offer a retry path (e.g., back to checkout). Do not auto-redirect to a generic error page — that loses context. For codes, see SDK Error Codes.

링크 복사Common — Payment Confirmation API (one-time payment shared)

Scenarios 5.A·5.B·5.C require calling the confirm API on the server after the client payment request to finalize. 5.D (billing) and 5.E (cancel) are separate flows.

Use the merchant's intended amount at request time for amount, not the successUrl query (Critical 2.2).

링크 복사5.A One-time — Payment Widget (default)

  • Entry point: tossPayments.widgets({ customerKey })
  • Flow: setAmount({ value, currency: "KRW" })renderPaymentMethodsrenderAgreementrequestPayment({ orderId, orderName, successUrl, failUrl }) → successUrl → server confirm
  • Key: SDK auto-renders payment method/agreement UI. Merchant only provides container divs.
  • Full code: Payment Widget Guide, V2 SDK Reference

Canonical flow (baseline pattern for any one-time payment — use this as the default mental model):

링크 복사5.B One-time — Standard Payment Window

  • Entry point: tossPayments.payment({ customerKey }).requestPayment({ method, amount: { value, currency: "KRW" }, orderId, orderName, successUrl, failUrl, ... })
  • Flow: Single client call → payment window → successUrl → server confirm
  • Key: Merchant builds payment method selection UI. Branch by method (CARD, VIRTUAL_ACCOUNT, TRANSFER, MOBILE_PHONE, EASY_PAY, CULTURE_GIFT_CERTIFICATE, etc.)
  • Full code: Payment Window Guide

링크 복사5.C Async — Virtual Account

  • Entry point: tossPayments.payment().requestPayment({ method: "VIRTUAL_ACCOUNT", amount: { value, currency: "KRW" }, virtualAccount, orderId, orderName, successUrl, failUrl, customerEmail?, customerName?, customerMobilePhone? })
  • virtualAccount fields: One of validHours or dueDate is required. cashReceipt, escrowProducts are optional.
  • Customer info: customerEmail/customerName/customerMobilePhone are optional in SDK but practically needed for deposit notification and refund. Recommended to collect.
  • Flow: Issue → confirm API call (response status: WAITING_FOR_DEPOSIT) → wait for deposit → DEPOSIT_CALLBACK webhook → query API → confirm status: DONE → mark as completed
  • Key: Request time ≠ completion time. Do not mark as completed on issue response. DEPOSIT_CALLBACK webhook handling required.
  • Full code: , Webhook Events

링크 복사5.D Recurring — Auto-billing

Billing key issuance → server calls billing endpoint for recurring payments. Two methods for billing key issuance.

SDK method (default):

  • Step 1 (client): payment.requestBillingAuth({ method: "CARD" }) → successUrl receives customerKey, authKey
  • Step 2 (server): POST /v1/billing/authorizations/issue (authKeybillingKey)
  • Step 3 (server): POST /v1/billing/{billingKey} (recurring payment)

API method (separate contract required — non-authenticated payment qualification + PCI-DSS):

  • Server: POST /v1/billing/authorizations/card (card info directly) → billingKey
  • Recurring payment with billing key is the same as SDK step 3

Key: Billing key payment does NOT use requestPayment/successUrl//v1/payments/confirm flow. Server-only.

Full code: Auto-billing Guide, Billing API

링크 복사5.E Cancel·Refund·Query

  • Cancel: POST /v1/payments/{paymentKey}/cancel + { cancelReason }
  • Partial cancel: Add cancelAmount to body
  • Virtual account refund: Add refundReceiveAccount (bank/account number/holder name) to body
  • Query: GET /v1/payments/{paymentKey} or GET /v1/payments/orders/{orderId}
  • Full code: Cancel API, Query API

링크 복사6. Payment Method Pitfalls

Even after the scenario (5.A~5.E) is set, each payment method has caveats. Flow mapping is in section 5; this section is pitfalls only.

Payment methodCoding caveat
Virtual accountDEPOSIT_CALLBACK webhook handling required. Do not mark completed on issue response. (Scenario 5.C)
Easy payKakaoPay testable only with contracted MID key. Payco testable only with live key. Apple Pay shown only on iPhone/Mac Safari.
TransferQuick Account Transfer and BankPay differ in identity verification and cancellation policy.
Mobile / Gift certificatePer-method limit policies vary.
Non-authenticated paymentPayment with card info only (number, expiry, DOB, password) without identity verification. Separate merchant contract required.
Auto-billingBilling key payment is server-only (does NOT use requestPayment/successUrl//v1/payments/confirm flow). (Scenario 5.D)

Key terms:

  • Transaction — Each approve/cancel/partial-cancel from a payment is a "transaction". Identified by transactionKey.
  • Settlement — Paid out by transaction date + business day. General/scheduled settlement.

For payment method policies: , , , , , , , .

링크 복사7. Post-Processing Patterns

링크 복사7.1 Idempotency-Key

  • Available on all POST APIs (GET ignored).
  • Max 300 chars, UUID v4 recommended.
  • Valid for 15 days from first request.
  • Same idempotency key returns the first response (prevents duplicate payments).

For details, see Auth & Headers.

링크 복사7.2 Webhooks

Webhook typeEvent examplesVerification
General paymentPAYMENT_STATUS_CHANGED, DEPOSIT_CALLBACK, CANCEL_STATUS_CHANGEDNo signature header. Re-call Payment Query API with paymentKey to verify status.
Payouts/Sellerpayout.changed, seller.changedVerify tosspayments-webhook-signature header with HMAC SHA-256.

For details, see Webhook Events.

링크 복사7.3 Environment

  • Test environment: Key prefix test_*. No real deposit. Virtual account number prefixed with X. KakaoPay/Payco have separate policies.
  • Live environment: Key prefix live_*. Real deposits.

For details, see Environment Setup.

링크 복사8. Common Mistakes

Frequently wrong patterns when LLMs generate Toss Payments code.

Wrong patternCorrect pattern
Authorization: Basic base64(SECRET_KEY) (no colon)Authorization: Basic base64(SECRET_KEY:) (colon required)
Pass successUrl amount directly to confirm APICompare with stored order amount first, then pass
Call server API (api.tosspayments.com/*) with client keyUse secret key for server APIs
Hardcode secret key without .env, push to GitHubUse environment variable, add to .gitignore
Call V2 methods on V1 SDK URL (/v1/payment-widget)Use https://js.tosspayments.com/v2/standard for V2
Call updateAmount() in V2 Payment WidgetUse setAmount() in V2 (updateAmount removed)
requestPayment("CARD", {...}) (V1 signature) in V2 Payment WindowrequestPayment({ method: "CARD", amount: {...}, ... }) (V2 unified signature)
amount: 15000 (number) in V2 BrandPayamount: { value: 15000, currency: "KRW" } (object)
Mark virtual account as completed on issue responseConfirm via DEPOSIT_CALLBACK webhook or query API
Implement tosspayments-webhook-signature for general payment webhookGeneral payment webhook has no signature header. Re-verify via Query API with paymentKey
Add Idempotency-Key to GET requestIdempotency-Key applies only to POST (ignored on GET)
Retry idempotent error by changing only the keyInspect the error first before retry (risky)
Manage test/live keys in the same env variableSeparate by test_*/live_* prefix
Pass amount field as a stringamount.value is integer, amount.currency is string ("KRW")
Use requestPayment flow after billing key issuanceBilling key payment is server-only (/v1/billing/{billingKey})
Treat confirm API failure as immediate payment failureCheck status with Query API before branching (may be already authenticated/approved)
Call confirm API after failUrl redirectfailUrl is auth failure/cancellation. Do not call confirm API; show message by code
Use email/phone/member ID directly as customerKeyUse unpredictable values (UUID; 2~300 chars; at least one special char). For non-members, ANONYMOUS
Generate orderId in arbitrary format (whitespace/non-ASCII/etc.)Letters/digits/-_, 6~64 chars
Generate customerKey with 1 char (e.g., "a")Min 2 chars, must include at least one special char (-_=.@)

링크 복사9. Meta·Reference Routing

Scenario-specific full-code routing is in section 5 (entry points). This section is for meta/operations/reference information beyond scenarios.

링크 복사Reference (full specs)

What you needPage
Full API specAPI Reference
V2 JS SDK methodsSDK Reference
SDK error codesError Codes
Cancel/refund detailsCancel API
Payment query detailsQuery API
Webhook event specWebhook Events
Auth header detailsAuthorization Header

링크 복사Operations·Environment

What you needPage
Environment setup (test/live)Environment Setup
API key issuance/managementAPI Keys Guide
Payment flow for humansPayment Flow Guide

링크 복사LLM·MCP

What you needPage
Full docs index (LLM standard format) — primary routing resourcellms.txt
MCP server·LLM integration toolsLLMs Integration Guide
  • 더 궁금한 내용이 있나요?
  • 코드 샘플을 참고하세요
  • 기술지원이 필요한가요?
    실시간 문의|이메일 보내기