# Environments & Test Data

One API for testing and for production: test networks and the products' sandboxes are chosen per request, with the same credentials and the same base URL.

## Overview

- **There is no separate sandbox host.** Every call goes to `https://api.aureahub.com`, with your tenant's API key and secret.
- **A request chooses its environment** with `isTestnet` — in the body, or in the query of a `GET`: `true` for the test networks and the sandboxes, `false` or omitted for production. Each route's page says where it reads it.
- **Data is kept apart by environment.** A wallet is on a mainnet or on a testnet; a bank ramp customer, a card onramp session, a webhook endpoint and an Earn position each belong to one environment. Your users and their accounts are the same in both.

## Test and Live

**Your tenant has one API key and one secret, and they work in both environments.** There are no separate test keys: the key's `ak_live_` prefix is part of its format and does not mean production. What makes a call a test is the call itself:

- `isTestnet: true` (in the body, or the query of a `GET`) sends it to the test networks and the products' sandboxes. Omitted or `false`, it is production.
- A testnet wallet only ever works on its testnet, so a send, a balance or a swap from it can never touch a mainnet. The risk is the other way round: a test server that forgets `isTestnet` creates mainnet wallets and production records.

To keep test and production apart:

- **Give your test servers a test-only credential.** Sign from them with a [server credential](https://docs.aureahub.com/docs/guide-server-credentials.md) registered with `testOnly: true` [Coming soon, upon request](https://docs.aureahub.com/docs/feature-availability.md): its tokens are accepted only on requests for a testnet, and refused `403` `TEST_ONLY_CREDENTIAL` on anything else — a forgotten `isTestnet` fails instead of reaching a mainnet ([Server Credentials › Test-Only Credentials](https://docs.aureahub.com/docs/guide-server-credentials.md)). Without it, give them a credential of their own anyway — its own role, IP allow-list and expiry — instead of the API secret: you can revoke it without touching production.
- **Set `isTestnet` in one place** in your test configuration, and have your test server refuse to start without it.
- **Use test users** with addresses you recognise and testnet wallets only (Test Users and Wallets, below), and a `sandbox` webhook endpoint (Webhooks per Environment, below).

> Note: **Aurea Pay works differently.** Payment links and the hosted checkout have keys per environment, `sk_test_…` and `sk_live_…`, managed in the Pay dashboard: see [Pay: Payment Links & Checkout](https://docs.aureahub.com/docs/products-pay.md). The keys of one product never work on the other.

> Tip: **No tenant yet?** Ask for a sandbox tenant: you receive its API key and secret and your first administrator's account. We reply within one business day.
>
> [Request sandbox access](https://access.aureahub.com/login?request=build&source=sandbox)

## Mainnet and Testnet

- List the networks your tenant can use in each environment: [`GET /v1/tokens/meta/chains?isTestnet=true`](https://docs.aureahub.com/docs/tokens-chains.md). A chain's `id` is the same on both: `polygon` with `isTestnet: true` is Polygon Amoy ([Supported Chains](https://docs.aureahub.com/docs/supported-blockchains.md)).
- Create a test wallet with `isTestnet: true` ([Create Wallet](https://docs.aureahub.com/docs/wallets-create.md)). Its address works only on the testnet; balances, sends and swaps read the wallet's own network.
- **Fund it** from a public faucet of that test network: send its test coin to the wallet's `address`. Test tokens of your token list come from their own test faucets or test issuers.
- A test network is listed once it is enabled for your tenant with at least one active token: ask Aurea for one you need.

## Test Users and Wallets

- Test users are users of your tenant like any other: register them with your test app ([Register](https://docs.aureahub.com/docs/auth-register.md)), with addresses and names you recognise, and give them testnet wallets only.
- [List Users](https://docs.aureahub.com/docs/users-list.md) takes `isTestnet` to show the users whose wallets are on test networks.
- Keep test credentials and real ones apart on your side: a test user signs in with the same routes and gets the same kind of tokens.

## The Sandbox

The products that move money in and out — available on request ([Feature Availability](https://docs.aureahub.com/docs/feature-availability.md)) — have a sandbox of their own, chosen with `isTestnet: true`:

- **The bank ramp.** A user has a separate customer profile in each environment, with its own KYC. In the sandbox, [Simulate a Deposit](https://docs.aureahub.com/docs/sandbox-deposit.md) pays a bank transfer into the user's own sandbox virtual account; production answers `404`. Payouts from a wallet are tested the same way, with `isTestnet: true` ([Bank Ramp: Payout](https://docs.aureahub.com/docs/guide-fiat-payout.md)). Your tenant's settings in each environment: [What Your Tenant Offers](https://docs.aureahub.com/docs/bank-settings.md).
- **The card onramp.** The sandbox is the payment provider's test mode, with its own pairs and currencies ([Configuration](https://docs.aureahub.com/docs/card-onramp-config.md)) and the test card and codes in [Card Onramp › Testing](https://docs.aureahub.com/docs/guide-card-onramp.md).
- **Earn.** A product your tenant has on a testnet is listed with `isTestnet=true`; deposits and withdrawals there move test tokens ([Earn](https://docs.aureahub.com/docs/guide-earn.md)).
- **Identity verification** [Coming soon, upon request](https://docs.aureahub.com/docs/feature-availability.md). A user has separate verifications in each environment: verify with test identities in the sandbox, and again for real in production ([Identity Verification › Testing in the Sandbox](https://docs.aureahub.com/docs/guide-identity.md)).

## A Pay-In Dry Run

The bank ramp end to end in the sandbox, for a user whose wallets are custodial — once your tenant has the bank ramp, with KYC and pay-in on in the sandbox ([Bank Ramp: Setup & Customers](https://docs.aureahub.com/docs/guide-bank-customers.md)):

```typescript
const API = 'https://api.aureahub.com';
const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' };
const post = (path: string, body?: object) =>
  fetch(API + path, { method: 'POST', headers, body: body ? JSON.stringify(body) : undefined }).then(r => r.json());

// 1. Hosted KYC in the sandbox: open session.onboardingUrl and complete it
const session = await post('/v1/ramp/bank/payin/onboard-session', { returnUrl: 'https://app.example.com/kyc/done', isTestnet: true });

// 2. Read the result
const kyc = await post('/v1/ramp/bank/payin/sync-status', { isTestnet: true });   // canInitiateDeposit: true

// 3. A sandbox virtual account, paid out to the user's Solana Devnet wallet
const pm = await post('/v1/ramp/bank/payin/initiate', { cryptoCurrency: 'EURC_TEST', network: 'SolanaDevnet' });

// 4. A simulated bank transfer into it
await post('/v1/ramp/bank/payin/sandbox/simulate-deposit', { paymentMethodId: pm.paymentMethodId, amount: 100 });

// 5. A few seconds later the deposit is listed
const { deposits } = await fetch(API + '/v1/ramp/bank/payin/deposits?isTestnet=true', { headers }).then(r => r.json());
```

- Step 1 makes the user's Solana Devnet wallet when they have none: leave `destinationAddress` out at step 3. A watch-only wallet is never a destination.
- A simulated deposit is listed once the bank ramp's sandbox reports it, usually a few seconds after the call.
- KYC in the bank ramp's sandbox accepts test identities; what it asks for is decided by the bank ramp.

## Webhooks per Environment

A webhook endpoint belongs to one environment: `sandbox` endpoints receive the events of test networks and sandboxes, `production` endpoints the others. Register a sandbox endpoint for your test server and send it a test event ([Send a Test](https://docs.aureahub.com/docs/webhook-endpoint-test.md)). See [Webhooks & Events](https://docs.aureahub.com/docs/guide-events.md).

## Before Going Live

1. Your API secret is in your server's configuration only, and you know how to rotate it ([Credentials & Rotation](https://docs.aureahub.com/docs/guide-credentials.md)).
2. Every call that moves funds sends an `Idempotency-Key`, and a retry reuses it ([Idempotency](https://docs.aureahub.com/docs/idempotency.md)).
3. Your code branches on the HTTP status and on `details.code`, never on `message` ([Errors & Codes](https://docs.aureahub.com/docs/errors.md)), and handles `429` ([Rate Limits](https://docs.aureahub.com/docs/rate-limiting.md)).
4. Your server verifies every webhook's signature, and treats an unknown status or event type as not final.
5. Amounts are integer strings in the token's smallest unit ([Amount Units](https://docs.aureahub.com/docs/amounts.md)).
6. You have a `production` webhook endpoint, and every request you send in production omits `isTestnet` or sends `false`.

---

Web version: https://docs.aureahub.com/#guide-environments
