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

# Sandbox

> Fund a test wallet, reach the right storefront, and create a test investor without a KYC document.

Sandbox is a full deployment of the Brickken platform on public testnets. Everything you build
against it uses the same API, the same methods, and the same contracts as production.

| Environment | API base URL                       | App URL                             |
| ----------- | ---------------------------------- | ----------------------------------- |
| Sandbox     | `https://api.sandbox.brickken.com` | `https://dapp.sandbox.brickken.com` |
| Production  | `https://api.brickken.com`         | `https://dapp.brickken.com`         |

<Note>
  Sandbox and production are separate deployments with separate databases. An API key issued for one does not work on the other.
</Note>

## Sandbox is a separate world

Sandbox and production have separate databases, separate API keys, and separate contract
deployments. An asset created in Sandbox does not exist in production, and vice versa.

That extends to the web surfaces, which is the single most common source of confusion:

| Surface          | Sandbox host                                  |
| ---------------- | --------------------------------------------- |
| API              | `https://api.sandbox.brickken.com`            |
| Dashboard        | `https://dapp.sandbox.brickken.com`           |
| Asset storefront | `https://<SYMBOL>.store.sandbox.brickken.com` |

<Warning>
  The `sandbox` label comes **after** `store` — `tusc.store.sandbox.brickken.com`, not
  `sandbox.tusc.store.brickken.com`. The production storefront will happily load its application
  shell for any host, so a wrong URL looks like a broken page rather than a wrong environment.
  Symptoms of using a production host for a Sandbox asset are an investor page stuck on **Loading
  Secure Environment**, an Investor Hub that never finishes loading, and `License for user not
      found`.
</Warning>

The KYC widget resolves which asset it is verifying for from the host it is served from. On a
generic host that lookup returns nothing and the widget spins forever. Start the KYC flow from the
asset's own storefront.

## Networks

| Network              | Decimal    | Hex        |
| -------------------- | ---------- | ---------- |
| Ethereum mainnet     | `1`        | `0x1`      |
| Base mainnet         | `8453`     | `0x2105`   |
| BNB Smart Chain      | `56`       | `0x38`     |
| Polygon mainnet      | `137`      | `0x89`     |
| Sepolia testnet      | `11155111` | `0xaa36a7` |
| Polygon Amoy testnet | `80002`    | `0x13882`  |

Pass `chainId` as decimal or hex. Client tooling normalizes common values.

Sandbox assets in this guide use Ethereum Sepolia (`11155111` / `aa36a7`). Every wallet that signs
a transaction needs Sepolia ETH for gas, from any public Sepolia faucet.

## Payment tokens

Sandbox uses its own payment-token registry. A token you obtained from an unrelated public faucet
will not match the contract the escrow actually pulls from, which is why generic "Sepolia USDT"
never works.

### Resolve the token from the API

Always let the API tell you which contract an asset takes as payment, rather than hardcoding one.
Different assets can be configured with different payment tokens.

```bash theme={null}
curl --request GET \
  --url 'https://api.sandbox.brickken.com/get-tokenizer-info?tokenSymbol=EXMPL' \
  --header 'x-api-key: YOUR_API_KEY'
```

`paymentTokenAddress` in the response is the authoritative value for that asset. The `newInvest`
prepare response also carries `paymentTokenAddress` and `paymentTokenSymbol` for the specific
offering.

### Registered Sepolia payment tokens

<Warning>
  These addresses are a convenience for funding a wallet by hand. They can change — one of them
  already has. Resolve the payment token through the API before you invest, and never hardcode an
  address in application code.
</Warning>

| Symbol | Contract                                     | Decimals | How to get test funds                                                 |
| ------ | -------------------------------------------- | -------- | --------------------------------------------------------------------- |
| `USDT` | `0x28d2B01854D0aBec267a3DDcad9163580E6E8604` | 6        | Request test funds from [tech@brickken.com](mailto:tech@brickken.com) |
| `USDC` | `0xb10cE8e28aEb1ae27b968Fb3bfed2FD7dd52daCb` | 6        | Request test funds from [tech@brickken.com](mailto:tech@brickken.com) |
| `BKN`  | `0x2458fB1620ff84019d73216fF20aA1F82Bc8E4CC` | 18       | See [BKN Faucet](/api-reference/endpoint/bkn-faucet)                  |

`USDT` is the default payment token on Sepolia when a request does not specify one, so it is the
path of least resistance for testing.

To fund a test wallet, send the wallet address and the amount you need to
[tech@brickken.com](mailto:tech@brickken.com).

<Note>
  These are the payment tokens of the Dapp API. The Agentic API settles x402 payments on a separate
  rail with its own assets, including Circle's own testnet USDC, so an address you see quoted for an
  x402 payment is not interchangeable with the ones above.
</Note>

## Skip KYC while you build

**Do not run the KYC flow for your test investors.** Sandbox KYC is a real Sumsub verification with
a document upload, and it proves nothing about your integration. Create investors with
`needKyc: false` and the compliance gate is satisfied from the start — no documents, no waiting, and
a fresh test investor whenever you need one.

`needKyc` is accepted on [`create-kyc-link`](/api-reference/endpoint/create-kyc-link), on each
`userToWhitelist` entry of the [`whitelist`](/api-reference/endpoint/prepare-whitelist) method, and
on each `userToMint` entry of [`mintToken`](/api-reference/endpoint/prepare-mintToken).

<Tabs>
  <Tab title="API">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.sandbox.brickken.com/create-kyc-link' \
      --header 'x-api-key: YOUR_API_KEY' \
      --header 'Content-Type: application/json' \
      --data '{
        "email": "builder+sbx1@example.com",
        "needKyc": false,
        "walletAddress": "0x1111111111111111111111111111111111111111"
      }'
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    brickken kyc create-link --email builder+sbx1@example.com --need-kyc false
    ```
  </Tab>
</Tabs>

Confirm the result before going further:

```bash theme={null}
curl --request GET \
  --url 'https://api.sandbox.brickken.com/get-investor-info?tokenSymbol=EXMPL&email=builder%2Bsbx1@example.com' \
  --header 'x-api-key: YOUR_API_KEY'
```

`complianceStatus` should read `NOT_REQUIRED`, and `walletAddress` should be the address you
passed. An investor with a null `walletAddress` cannot invest.

<Warning>
  `needKyc: false` is only applied when the investor record is created. For an email that already
  has an account the stored value wins and cannot be downgraded, so use a fresh address — a `+`
  alias such as `builder+sbx2@example.com` is enough.
</Warning>

### Rehearse the real flow once, before production

`needKyc: false` is a Sandbox affordance. In production the request is rejected with
`needKyc=false is only available in the sandbox environment`, so every real investor goes through
Sumsub.

That makes one rehearsal worthwhile before you go live — enough to see the verification screens your
investors will meet and to confirm your polling of `complianceStatus` behaves. A sample document
image is enough to reach a green applicant in the Sandbox tenant; no genuine liveness check is
required.

<Warning>
  Never upload real identity documents to a test account.
</Warning>

<Note>
  KYC and whitelisting are independent. KYC is an off-chain, per-investor compliance record keyed
  by email. Whitelisting is an on-chain, per-token permission keyed by wallet address. Whitelisting
  a wallet does not approve KYC, and passing KYC does not whitelist a wallet — an offering needs
  both.
</Note>

## Identities are shared across the environment

A Brickken account is one identity for the whole Sandbox environment, not one per asset:

* Login is global.
* KYC is global — one record per email, reused by every asset that investor touches.
* Whitelisting is **per asset** — each token tracks its own relationship with an investor.

An email already registered as a tokenizer cannot also be onboarded as an investor. Give test
investors their own email, separate from the account you issue with; otherwise investor lookups
return `Investor not found`.

<CardGroup cols={2}>
  <Card title="Troubleshooting" icon="stethoscope" href="/api-reference/guides/troubleshooting">
    Decode a failed call, from validation errors to raw revert data.
  </Card>

  <Card title="Tokenize an asset and run an STO" icon="route" href="/api-reference/guides/tokenize-and-run-an-sto">
    The full lifecycle, end to end.
  </Card>
</CardGroup>
