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

# Sandbox Testing

> Test payments end-to-end without real money using the sandbox processor

# Sandbox Testing

**Time**: \~10 minutes | **Difficulty**: Beginner

The sandbox processor lets you test the full payment flow — checkout, payment processing, order creation, webhooks — without connecting a real payment gateway or charging real cards.

***

## How the Sandbox Processor Works

The sandbox processor simulates a payment gateway. When a customer submits payment on a checkout that uses a sandbox processor:

1. The payment is **always approved** (no real card validation)
2. An order is created in TagadaPay
3. Webhooks fire as if a real payment occurred
4. Subscriptions are created and can be billed

This makes it perfect for:

* Testing your checkout flow end-to-end
* Verifying webhook integrations
* Testing subscription billing cycles
* QA before going live with a real processor

***

## Step 1: Create a Sandbox Processor

<Tabs>
  <Tab title="Node SDK">
    ```ts theme={null}
    import Tagada from '@tagadapay/node-sdk';
    const tagada = new Tagada('your-api-key');

    const { processor } = await tagada.processors.create({
      processor: {
        name: 'Test Sandbox',
        type: 'sandbox',
        enabled: true,
        supportedCurrencies: ['USD', 'EUR', 'GBP'],
        baseCurrency: 'USD',
        options: {
          testMode: true,
        },
      },
    });

    console.log('Sandbox processor:', processor.id);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://app.tagadapay.com/api/public/v1/processors/create \
      -H "Authorization: Bearer your-api-key" \
      -H "Content-Type: application/json" \
      -d '{
        "processor": {
          "name": "Test Sandbox",
          "type": "sandbox",
          "enabled": true,
          "supportedCurrencies": ["USD", "EUR", "GBP"],
          "baseCurrency": "USD",
          "options": { "testMode": true }
        }
      }'
    ```
  </Tab>
</Tabs>

***

## Step 2: Create a Payment Flow

Create a payment flow that routes all traffic to your sandbox processor:

```ts theme={null}
const flow = await tagada.paymentFlows.create({
  data: {
    name: 'Sandbox Flow',
    strategy: 'simple',
    fallbackMode: false,
    maxFallbackRetries: 0,
    threeDsEnabled: false,
    stickyProcessorEnabled: false,
    pickProcessorStrategy: 'weighted',
    processorConfigs: [
      {
        processorId: processor.id,
        weight: 100,
        disabled: false,
        nonStickable: false,
      },
    ],
    fallbackProcessorConfigs: [],
    abuseDetectionConfig: null,
  },
});
```

***

## Step 3: Assign to Your Store

Assign the sandbox payment flow to your store. You can pass it at store creation:

```ts theme={null}
const store = await tagada.stores.create({
  name: 'Test Store',
  baseCurrency: 'USD',
  presentmentCurrencies: ['USD', 'EUR'],
  chargeCurrencies: ['USD'],
  selectedPaymentFlowId: flow.id,
});
```

Or if your store already exists, assign it via the dashboard: **Store Settings → Payments → Select Payment Flow**.

***

## Step 4: Complete the Setup

Follow the [Merchant Quick Start](/developer-tools/node-sdk/merchant-quickstart) to create a product and funnel. Once your checkout is live, any payment submitted will go through the sandbox processor.

***

## Testing Payments

### On the Checkout Page

1. Open your checkout URL in a browser
2. Fill in any email and shipping details
3. Enter **any card number** — the sandbox accepts everything:
   * `4242 4242 4242 4242` (or any 16 digits)
   * Any future expiry date
   * Any 3-digit CVC
4. Submit payment
5. The order is created and you're redirected to the thank you page

### Via the Headless API

You can also create a checkout session programmatically and share the link:

```ts theme={null}
const session = await tagada.checkout.createSession({
  storeId: store.id,
  items: [{ variantId: 'variant_...', quantity: 1 }],
  currency: 'USD',
  checkoutUrl: 'https://your-funnel-checkout-url.cdn.tagadapay.com/checkout',
});

console.log('Test checkout:', session.redirectUrl);
```

***

## Verifying Results

After a sandbox payment, verify everything worked:

### Check Orders

```ts theme={null}
const orders = await tagada.orders.list({
  storeId: store.id,
  page: 1,
  per_page: 5,
});
console.log('Latest orders:', orders.data);
```

### Check Payments

```ts theme={null}
const payments = await tagada.payments.list({
  pagination: { page: 1, pageSize: 5 },
  filters: { storeIds: [store.id] },
});
console.log('Latest payments:', payments.data);
```

### Check Webhooks

If you've configured webhooks, they fire for sandbox payments exactly as they would for real ones:

```ts theme={null}
const webhooks = await tagada.webhooks.list(store.id);
console.log('Configured webhooks:', webhooks);
```

***

## Testing Subscriptions

The sandbox processor fully supports subscription billing. Create a recurring product and test the billing cycle:

```ts theme={null}
// Create a subscription product
await tagada.products.create({
  storeId: store.id,
  name: 'Monthly Membership',
  active: true,
  variants: [{
    name: 'Standard',
    sku: 'membership-monthly',
    grams: 0,
    price: 1999,
    compareAtPrice: 0,
    active: true,
    default: true,
    prices: [{
      currencyOptions: { USD: { amount: 1999 } },
      recurring: true,
      interval: 'month',
      intervalCount: 1,
      billingTiming: 'in_advance',
      default: true,
    }],
  }],
});
```

When a customer subscribes through the checkout:

* The initial payment is processed through the sandbox
* The subscription is created in TagadaPay
* Rebilling occurs on schedule (processed through the sandbox)
* You can manage the subscription via the API or dashboard

***

## Sandbox vs Production

| Behavior        | Sandbox            | Production           |
| --------------- | ------------------ | -------------------- |
| Card validation | Accepts any card   | Real card validation |
| Charges         | No real money      | Real charges         |
| Orders          | Created normally   | Created normally     |
| Webhooks        | Fire normally      | Fire normally        |
| Subscriptions   | Created and billed | Created and billed   |
| 3D Secure       | Skipped            | Enforced if enabled  |
| Refunds         | Simulated          | Real refunds         |

***

## Going Live

When you're ready for production:

1. Create a real processor (Stripe, NMI, Adyen, etc.) with production credentials
2. Create a new payment flow using the real processor
3. Update your store's payment flow assignment
4. Your checkout now processes real payments

```ts theme={null}
// 1. Real processor
const { processor: stripeProcessor } = await tagada.processors.create({
  processor: {
    name: 'Stripe Production',
    type: 'stripe',
    enabled: true,
    supportedCurrencies: ['USD', 'EUR'],
    baseCurrency: 'USD',
    options: {
      secretKey: 'sk_live_...',
      publicKey: 'pk_live_...',
      webhookSecret: 'whsec_...',
    },
  },
});

// 2. Production flow
const prodFlow = await tagada.paymentFlows.create({
  data: {
    name: 'Production Flow',
    strategy: 'simple',
    fallbackMode: false,
    maxFallbackRetries: 0,
    threeDsEnabled: true,
    stickyProcessorEnabled: false,
    pickProcessorStrategy: 'weighted',
    processorConfigs: [
      { processorId: stripeProcessor.id, weight: 100, disabled: false, nonStickable: false },
    ],
    fallbackProcessorConfigs: [],
    abuseDetectionConfig: null,
  },
});

// 3. To switch a store's payment flow, update it in the dashboard
// or recreate the store with the new flow ID
```

<Tip>
  You can keep the sandbox processor and flow around for ongoing testing. Just create a separate test store that uses the sandbox flow.
</Tip>

***

## Cleanup

When done testing, archive the sandbox processor:

```ts theme={null}
await tagada.processors.del([processor.id]);
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Merchant Quick Start" icon="rocket" href="/developer-tools/node-sdk/merchant-quickstart">
    Complete setup from zero to live checkout
  </Card>

  <Card title="Multi-PSP Routing" icon="route" href="/developer-tools/node-sdk/multi-stripe-routing">
    Set up cascade routing across multiple processors
  </Card>

  <Card title="Headless Payments (Frontend)" icon="code" href="/developer-tools/payments/headless-payments">
    Build your own checkout UI with client-side card tokenization
  </Card>

  <Card title="Webhooks" icon="webhook" href="/api-reference/introduction">
    Configure webhooks to receive payment events
  </Card>
</CardGroup>
