> ## Documentation Index
> Fetch the complete documentation index at: https://razorpay.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Test your Server-to-Server integration end to end in Test Mode against simulated banks, networks and NPCI before you go live.

Available in
🇮🇳 India

Test Mode lets you run your whole integration against simulated banks, card networks and NPCI before you take real payments. You use the same APIs as in live mode. Only the keys change.

> [!NOTE]
>
> **Methods available for testing**
>
> Test Mode for S2S currently supports **Cards**, **UPI Intent**, **UPI QR** and **UPI Collect** for one-time payments, and **Card recurring**, **UPI Autopay Intent**, **UPI Autopay QR** and **UPI Autopay Collect** for recurring payments. More methods are coming soon.

This guide is in five parts, in the order you should test:

1. This overview — setup and the S2S payment flow.
2. [Orders](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/orders.md) — create orders and test every order scenario.
3. [Refunds](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/refunds.md) — test Normal and Instant refunds, failures and the fallback between them.
4. [Best Practices](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/best-practices) — webhooks, reconciliation, retries, late authorisation and more.
5. The page for each method you integrate. Method pages all follow the same structure, so once you've read one you know where to find anything on another.

## Build Your Test Plan

Pick what you are integrating and read the matching pages in order. Scenario IDs are the same on every page and in support conversations, so you can reference them when you raise a ticket.

| Common setup | Pages to read, in order |
| - | - |
| Card recurring only | Orders → Best Practices → [Card Recurring](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/card-recurring) |
| All recurring (no Collect) | Orders → Best Practices → [Card Recurring](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/card-recurring) → [UPI Autopay Intent](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/upi-autopay-intent.md) → [UPI Autopay QR](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/upi-autopay-qr.md) |
| Cards and UPI one-time (no Collect) | Orders → Refunds → Best Practices → [Cards](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/cards) → [UPI Intent](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/upi-intent.md) → [UPI QR](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/upi-qr.md) |
| Everything | Orders → Refunds → Best Practices → every page under Method Testing below |

## 1. Before You Begin

1. Switch the Dashboard to **Test Mode** with the toggle at the top.
2. Generate test keys: **Account & Settings → API Keys → Generate Test Key**. Test keys start with `rzp_test_`.
3. Use the same endpoints (`https://api.razorpay.com`) and request bodies as live mode. Nothing else changes.
4. Add a test-mode webhook URL with a secret: **Account & Settings → Webhooks**. Subscribe to the events your method pages list.

> [!WARNING]
>
> **Watch Out!**
>
> No real money moves in Test Mode. Test VPAs, test tokens and test mandates work only in Test Mode. Webhooks set up in Test Mode do not carry over to live mode — set them up again before you go live.

## 2. The S2S Payment Flow

Every S2S payment follows the same eight steps. Only step 4, the next action, depends on the method. Each step has tests on one of the pages below.

**1. Customer pays**

Your payment page collects the method details. Only methods enabled on your account are shown and methods that are down are hidden.

**2. Create a customer (recurring only)**

Your server calls `POST /v1/customers` and stores `customer_id`. Card mandates and UPI Autopay need it on the authorisation order; one-time payments do not. Test a valid customer, a duplicate customer and a malformed contact or email.

**3. Create order**

Your server calls `POST /v1/orders` and stores the `order_id`. Test a valid order, every request error and retries with `unique_receipt`. See [Orders](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/orders.md).

**4. Create payment**

Your server calls the create-payment API with the method details and the real `ip`, `user_agent` and `referer`. Test success and failure triggers and a timed-out create.

**5. Show the next action**

Razorpay returns `redirect`, `otp_submit`, `intent` or `poll`. Test each next action your method returns.

**6. Customer authenticates**

3DS, OTP, UPI PIN or bank login. Test authentication success and failure triggers.

**7. Callback: verify the signature**

The customer returns with `razorpay_payment_id`, `razorpay_order_id` and `razorpay_signature`. Verify the signature against the stored `order_id` and reject a tampered value.

**8. Webhook: fulfil**

`order.paid` or `payment.captured` arrives. Fulfil once, only from the webhook. Test duplicates and out-of-order events.

**9. No webhook in time? Fetch**

Your reconciler calls `GET /v1/orders/:id/payments`. Test a missing webhook, a down endpoint and late authorisation.

## 3. How Simulation Works

There is no real bank on the other end, so you pick the outcome through the input you send. Cards use the card number; UPI uses the amount.

| Method | Pick the outcome with | Success | A specific failure | Anything else | Runs without a browser? |
| - | - | - | - | - | - |
| Cards | Test card number, then a button on the mock bank page | Success card + Success, or any OTP of 4–10 digits | Failure card + Failure | Any card + Failure returns `gateway_technical_error` | No, for 3DS. Native OTP runs over the API. |
| Card recurring | The card used at registration. Subsequent debits reuse it. | Register with a success card, then charge the token | Registration: failure card + Failure. Subsequent debit: register the debit failure card with Success, then charge the token | — | Registration: no. Subsequent debits: yes. |
| UPI Intent and QR | `amount` in paise | `100` | A reserved amount | Succeeds | Yes |
| UPI Collect | VPA + `amount` | `success@razorpay` + `100` | `failure@razorpay` + a reserved amount | `failure@razorpay` + any other amount fails | Yes |
| UPI Autopay | `amount` on the payment | `100` | A reserved amount. For debits, keep it below `max_amount`. | Available | Yes |

UPI reserved amounts follow one pattern. Amounts are in paise, so `201` is ₹2.01.

| Range | Cause | Examples |
| - | - | - |
| `1xx` | Bank and network | `101` bank system error, `104` bank slow to respond, `105` NPCI timeout |
| `2xx` | Customer account and limits | `201` insufficient funds, `204` wrong UPI PIN, `208` amount limit |
| `3xx` | Customer action | `301` request expired, `302` cancelled, `304` declined in app |
| `4xx` | Validation and risk | `401` invalid UPI ID, `404` risk decline, `406` duplicate request |

Each method page lists its own test cards or reserved amounts under "Test Kit" and the exact `error.reason` each one triggers under "Simulate Failures".

The same amount means the same cause on UPI one-time and UPI Autopay.

> [!NOTE]
>
> **Handy Tips**
>
> Testing recurring on cards and UPI? A card debit reaches its final state about 5 minutes after you create it; a UPI Autopay debit settles immediately. Poll `GET /v1/payments/:id` with a timeout instead of asserting straight after creation, or your automated tests will be flaky.

## 4. Read the Error Object

Every failure returns the same five fields. Build your handling on `reason` and `source`. Do not match on `description` — it is customer-facing text and can change.

| Field | What it tells you | Example |
| - | - | - |
| `error.code` | Error class | `BAD_REQUEST_ERROR`, `GATEWAY_ERROR`, `SERVER_ERROR` |
| `error.reason` | The specific cause. Branch on this. | `insufficient_funds` |
| `error.source` | Who caused it | `customer`, `issuer_bank`, `remitter_bank`, `business`, `gateway` |
| `error.step` | Where in the flow it failed | `payment_authentication`, `payment_debit_request` |
| `error.description` | Message you can show the customer | "Insufficient balance in your account…" |

| `error.source` | What to do |
| - | - |
| `customer` | Show the description. Let the customer retry or switch instrument. |
| `issuer_bank`, `remitter_bank`, `beneficiary_bank` | Retry later, or ask for another account. |
| `gateway`, `network`, `customer_psp`, `internal` | Temporary. Retry after a short wait. |
| `business` | Your request is wrong. Fix it in code. Retrying will not help. |

## 5. Two Kinds of Errors

| | API errors | Payment failures |
| - | - | - |
| When | The request itself is invalid | The payment was created and then failed |
| You see | HTTP 4xx/5xx with an error object | Payment status `failed` with an error object |
| Webhook | None | `payment.failed` |
| How to trigger | Send a bad request: missing field, wrong format, wrong key | Use a failure card or a reserved amount |

## 6. Webhooks and Reconciliation

* Verify `X-Razorpay-Signature` with your webhook secret on every event. Reject anything that fails.
* Return `2xx` quickly and process asynchronously.
* Webhooks are delivered at least once. Use the event ID to process each one once.
* In Test Mode, webhooks arrive almost instantly. In live mode they can take up to 12 minutes. If nothing arrives within a minute, poll `GET /v1/payments/:id`.
* When your records and the API disagree, the API is the source of truth.

## 7. What Test Mode Can't Do

Every method page marks what you can test with one of these labels:

| Label | Meaning | What you do |
| - | - | - |
| Available | Simulated in Test Mode | Test it here |
| Coming soon | Not simulated yet | Build to the spec. Check it on a test account in live mode until it ships. |
| Live only | Depends on real time windows, banks or customers. It won't be simulated. | Check it in a controlled live test with small amounts |
| Client-side | Runs on the customer's device, not on a Razorpay API | Test it on real devices |

## 8. Go-Live Checklist

See the full [Go-Live Checklist](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/json/v1/go-live-checklist.md) for the complete walkthrough. The essentials:

**Every method**

* Every scenario in your test plan passes.
* Live keys (`rzp_live_`) and a live webhook URL and secret are in place. Test cards and test VPAs fail in live mode.
* Signatures are verified on checkout callbacks and on webhooks.
* Duplicate webhooks are ignored.
* Failures are handled by `error.reason` and `error.source`, not by description text.
* Polling `GET /v1/payments/:id` works as a fallback when webhooks are late.
* You've noted your platform, checkout type and SDK versions, so you can upgrade cleanly.

**One-time methods (Cards, UPI)**

* Fulfil on `payment.captured` (or `order.paid`), never on the checkout callback alone.
* Handle the dismiss or cancel callback on Standard and Custom Checkout, so a closed checkout doesn't leave the order in limbo.
* Retry logic treats customer failures differently from bank and gateway failures.
* Auto-capture settings match your refund policy.

**Recurring methods (Card recurring, UPI Autopay)**

* Methods enabled. Recurring is enabled per method, and separately for test and live mode.
* Authorisation order. The token object carries the right `max_amount`, `frequency`, `expire_at` and, where relevant, `auth_type`, `recurring_type` and `recurring_value`.
* Recurring flag. Always send `recurring` and `customer_id`. Without the flag the payment silently becomes one-time and no token is created.
* Signatures. Verify `razorpay_signature` on the checkout callback, then fetch the payment before granting service.
* Failure handling. Tell temporary bank errors apart from permanent token failures. Retrying a dead token causes needless churn.
* Token management. Integrate fetch token by payment ID, fetch tokens by customer ID, cancel token and delete token. Check token state before every debit.
* Capture and late auth. Set auto-capture windows deliberately. Reconcile on the state at capture time so late authorisations aren't dropped.
* Webhooks with a fallback. Subscribe to at least `token.confirmed`, `token.cancelled`, `payment.captured` and `payment.failed`. Use the fetch APIs when webhooks are late.
* Refunds. Set `payment_capture` to manual on the authorisation payment if you don't want it auto-refunded. Integrate the Refunds API for debits.
* SDK versions. Record your platform, checkout type and server SDK version.

## Method Testing

> [card] [Cards (One-time)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/cards)
>
> Test one-time card payments, authentication, saved cards and tokens.

> [card] [UPI Intent (One-time)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/upi-intent.md)
>
> Test one-time UPI Intent payments.

> [card] [UPI QR (One-time)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/upi-qr.md)
>
> Test one-time UPI QR payments.

> [card] [UPI Collect (One-time)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/one-time/upi-collect.md)
>
> Test one-time UPI Collect payments.

> [card] [Card Recurring (Recurring)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/card-recurring)
>
> Test card mandate registration and subsequent debits.

> [card] [UPI Autopay Intent (Recurring)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/upi-autopay-intent.md)
>
> Test UPI Autopay mandates registered through Intent.

> [card] [UPI Autopay QR (Recurring)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/upi-autopay-qr.md)
>
> Test UPI Autopay mandates registered through QR.

> [card] [UPI Autopay Collect (Recurring)](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/recurring/upi-autopay-collect.md)
>
> Test UPI Autopay mandates registered through Collect.

### Related Information

* [Server-to-Server Integration](https://razorpay.com/docs/payments/payment-gateway/s2s-integration.md)
* [Orders](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/orders.md)
* [Refunds](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/refunds.md)
* [Best Practices](https://razorpay.com/docs/payments/payment-gateway/s2s-integration/test-s2s/best-practices)
