# 

## Prerequisites

* A client account in the sandbox environment — see [Create a client account](/docs/how-tos/setup/create-client-account)
* API credentials for the sandbox — see [Obtain API credentials](/docs/how-tos/setup/obtain-credentials)


## Step 1: Use the sandbox base URL

All sandbox requests use the development base URL.

| Environment | Base URL |
|  --- | --- |
| Sandbox | `https://api.dev.paradisegateway.net` |
| Production | `https://api.paradisegateway.net` |


Set the base URL in your application's configuration so you can switch between environments without changing code.

Shell (Bash)
```shell
export PARADISE_API_URL="https://api.dev.paradisegateway.net"
```

PowerShell
```powershell
$env:PARADISE_API_URL = "https://api.dev.paradisegateway.net"
```

Python
```python
import os

API_URL = os.getenv("PARADISE_API_URL", "https://api.dev.paradisegateway.net")
```

JavaScript
```javascript
const API_URL = process.env.PARADISE_API_URL
  || "https://api.dev.paradisegateway.net";
```

C#
```csharp
var apiUrl = Environment.GetEnvironmentVariable("PARADISE_API_URL")
    ?? "https://api.dev.paradisegateway.net";
```

Java
```java
String apiUrl = System.getenv().getOrDefault(
    "PARADISE_API_URL", "https://api.dev.paradisegateway.net");
```

Go
```go
apiURL := os.Getenv("PARADISE_API_URL")
if apiURL == "" {
    apiURL = "https://api.dev.paradisegateway.net"
}
```

PHP
```php
$apiUrl = getenv("PARADISE_API_URL") ?: "https://api.dev.paradisegateway.net";
```

## Step 2: Store your sandbox API key

Retrieve your sandbox API key (see [Obtain API credentials](/docs/how-tos/setup/obtain-credentials)) and store it as an environment variable.

Shell (Bash)
```shell
export PARADISE_API_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

PowerShell
```powershell
$env:PARADISE_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

Never commit credentials
Add environment variable files (`.env`, `.env.local`) to `.gitignore`. Do not hard-code API keys in source code.

## Step 3: Use test card numbers

The sandbox accepts specific test card numbers that simulate various outcomes. Real card numbers are rejected in the sandbox.

### Cards that approve

| Card number | Brand | CVV | Expiry |
|  --- | --- | --- | --- |
| `4111111111111111` | Visa | Any 3 digits | Any future date |
| `4111111111111234` | Visa | Any 3 digits | Any future date |
| `5500000000005678` | Mastercard | Any 3 digits | Any future date |


### Cards that decline

| Card number | Brand | Simulated result |
|  --- | --- | --- |
| `4000000000000002` | Visa | Decline — insufficient funds |
| `4000000000000069` | Visa | Decline — expired card |
| `4000000000000127` | Visa | Decline — CVV mismatch |


### Test bank accounts

| Routing number | Account number | Account type | Result |
|  --- | --- | --- | --- |
| `021000021` | `9876543210` | `checking` | Approved |
| `021000021` | `0000000001` | `checking` | Return — insufficient funds |


## Step 4: Send a test transaction

Verify your sandbox setup by processing a test sale.

```shell
curl -X POST \
  $PARADISE_API_URL/v1/transactions \
  -H "Content-Type: application/json" \
  -H "APIKEY: $PARADISE_API_KEY" \
  -d '{
    "type": "card_sale",
    "amount": 1999,
    "payment_method": {
      "type": "card",
      "pan": "4111111111111111",
      "expiry_month": "12",
      "expiry_year": "2028",
      "cardholder_name": "Test User",
      "cvv": "123",
      "address_line1": "123 Test St",
      "zip": "10001"
    }
  }'
```

A successful response returns `transaction_state: authorized` and `response_code: "00"`.

```json
{
  "id": "TRANSACTION-06OSTESTXYZ123456789ABCDE",
  "object": "transaction",
  "type": "card_sale",
  "transaction_state": "authorized",
  "response_status": "Approved",
  "response_code": "00",
  "response_message": "The API request is approved.",
  "amount": 1999,
  "correlation_id": "d4e5f6a7-b8c9-0123-def0-123456789abc"
}
```

## Step 5: Test error scenarios

Exercise your error handling by testing common failure cases.

| Scenario | How to trigger | Expected result |
|  --- | --- | --- |
| Declined transaction | Use decline test card `4000000000000002` | `response_status: Declined` |
| Invalid card | Send an invalid PAN like `1234567890123456` | `422 Validation failed` |
| Missing required field | Omit `amount` | `400 Bad Request` |
| Invalid API key | Use `APIKEY: invalid` | `401 Unauthorized` |
| Non-existent transaction | `GET /v1/transactions/TRANSACTION-DOESNOTEXIST` | `404 Not Found` |


## Sandbox vs. production differences

| Behavior | Sandbox | Production |
|  --- | --- | --- |
| Processor connections | Simulated | Live TSYS / Vericheck |
| Real funds | No | Yes |
| Test cards accepted | Yes | No — real cards only |
| Settlement | Simulated batch closure | Real batch clearing |
| ACH returns | Simulated on schedule | Real ACH network timeline |
| Rate limits | Same as production | Standard limits |


## Switching to production

When your integration is tested and ready, switch to production.

1. **Obtain production credentials** — create a production client account and API key using the production base URL.
2. **Update the base URL** — change `PARADISE_API_URL` to `https://api.paradisegateway.net`.
3. **Update the API key** — replace your sandbox key with the production key.
4. **Remove test card numbers** — production rejects test cards.
5. **Verify processor integrations** — ensure live TSYS and/or Vericheck integrations are configured.


For a complete checklist, see [Sandbox vs. production](/docs/get-started/sandbox-vs-production).

Before going live
Run your full test suite against the sandbox. Confirm that your error handling, retry logic, and webhook processing all work as expected before switching to production.

## Next steps

* [Quickstart](/docs/get-started/quickstart) — send your first test sale
* [Sandbox vs. production](/docs/get-started/sandbox-vs-production) — full environment comparison
* [Integration best practices](/docs/get-started/integration-best-practices) — security, idempotency, and retry guidance