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

# Testing in sandbox

> Magic values and triggers the Trace Finance sandbox accepts to simulate compliance and settlement outcomes during homologation.

## Overview

The sandbox base URL is `https://api.sandbox.tracefinance.com`. It runs the same state machines as production, so most requests follow the happy path by default: beneficiaries approve, payment instructions clear, and operations settle.

To exercise the other branches, the sandbox recognizes a set of deterministic magic values and triggers. Sending one forces a specific compliance or settlement outcome without waiting for a real upstream error, so you can develop and verify each path during homologation. The sections below list every trigger, grouped by the resource it acts on.

To build the webhook handler that receives the resulting events, see [Test webhooks in sandbox](/webhooks/test-in-sandbox).

## Beneficiaries

A beneficiary you create **auto-approves by default**. Use the triggers below to force other outcomes.

### Force the pending state

Send `entity.address.addressLine2` containing `no-auto` (case-sensitive, substring match) to keep the beneficiary in its initial pending state. Use this to validate UI states, polling, and webhook delivery before the decision lands.

```json theme={"theme":"tokyo-night"}
"address": {
  "addressLine1": "Rua Augusta, 500",
  "addressLine2": "Apto 12 no-auto"
}
```

### Force a rejection

Send any of the following values to receive a rejected beneficiary.

| Field                                                     | Value                     | Simulated reason             |
| --------------------------------------------------------- | ------------------------- | ---------------------------- |
| `entity.identificationDocument.value` (with `type: CPF`)  | `12345678909`             | Tax ID owner deceased        |
| `entity.identificationDocument.value` (with `type: CNPJ`) | `50676745000143`          | Company deregistered         |
| `entity.firstName` + `entity.lastName`                    | `John` + `Doe` (exact)    | Name match on sanctions list |
| `entity.address.country`                                  | `KP`, `IR`, `SY`, or `CU` | Sanctioned country           |

### Pix payment instructions

A Pix instruction either approves (auto-approves in sandbox, behind a real compliance review in production) or rejects after the review settles. Once approved, the customer's withdrawal against the instruction either completes or fails on the rail. The triggers below let you exercise both terminal-failure paths from your integration without waiting for real upstream errors.

#### Force a payment-instruction rejection

Use this trigger to develop and verify your `BENEFICIARY_PAYMENT_INSTRUCTION_REJECTED` handler. Submit a [`POST /v1/beneficiaries`](/api-reference/fx-payment/beneficiaries/create-beneficiary) request with the magic dict key on the Pix payment instruction:

| `paymentInstruction.dictKey`   | `paymentInstruction.dictKeyType` | Outcome                                                                                                     |
| ------------------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `reject@sandbox.trace.finance` | `EMAIL`                          | The Pix instruction is rejected; `BENEFICIARY_PAYMENT_INSTRUCTION_REJECTED` fires shortly after submission. |

```json theme={"theme":"tokyo-night"}
"paymentInstruction": {
  "rail": "PIX_KEY",
  "asset": "BRL",
  "dictKeyType": "EMAIL",
  "dictKey": "reject@sandbox.trace.finance"
}
```

Any other dict key follows the normal sandbox resolution path.

The endpoint responds `201 Created` with the new instruction in `PENDING_REVIEW`, the same shape as a normal submission. Shortly after, the [`BENEFICIARY_PAYMENT_INSTRUCTION_REJECTED`](/api-reference/fx-webhook/events/beneficiary/beneficiary-payment-instruction-rejected) webhook arrives with the rejection on the affected instruction:

```json theme={"theme":"tokyo-night"}
{
  ...,
  "instruction": {
    ...,
    "currentState": {
      "status": "REJECTED",
      "reason": {
        "code": "COMPLIANCE_REJECTED",
        "message": "An unknown error occurred.",
        ...
      },
      ...
    },
    ...
  },
  ...
}
```

A rejected instruction is terminal. To retry, register a new instruction, or a new beneficiary if the entity data was wrong.

#### Force a withdrawal failure

Use this trigger to develop and verify your `OPERATION_FAILED` handler. Register a beneficiary with any normal dict key so the instruction approves cleanly, then submit a [`POST /v1/operations/withdrawals`](/api-reference/fx-payment/operations/create-withdrawal) request using a quote whose `sourceAmount` cents select the simulated outcome:

| `sourceAmount` cents | `currentState.reason.code`         | `currentState.reason.message`                                                        |
| -------------------- | ---------------------------------- | ------------------------------------------------------------------------------------ |
| `.04`                | `INVALID_ACCOUNT`                  | "Invalid account."                                                                   |
| `.05`                | `CPF_CNPJ_ACCOUNT_HOLDER_MISMATCH` | "CPF/CNPJ of the receiving user is not consistent with the account holder credited." |
| `.06`                | `CLIENT_ACCOUNT_BALANCE_BLOCKED`   | "Client's account balance is blocked."                                               |
| `.07`                | `INSUFFICIENT_BALANCE`             | "Insufficient balance."                                                              |
| `.08`                | `TRANSACTION_LIMIT_EXCEEDED`       | "Daily equal transaction limit exceeded."                                            |
| `.09`                | `PROCESSING_ERROR`                 | "Transaction processing failed."                                                     |

Any other cents value settles the withdrawal normally. The trigger reads `sourceAmount` on the outbound withdrawal only, so beneficiary registration is unaffected and an approved beneficiary stays usable across all six triggers.

Quote `500.04` BRL → `500.04` BRL (or any same-asset amount whose cents are `.04`), then submit the withdrawal against the approved instruction. The endpoint responds `201 Created` with the operation in `REQUESTED`, the same shape as a normal withdrawal. Shortly after, the [`OPERATION_FAILED`](/api-reference/fx-webhook/events/operation/operation-failed) webhook arrives with the matching reason on `currentState`:

```json theme={"theme":"tokyo-night"}
{
  ...,
  "sourceAmount": { "value": "500.04", "asset": "BRL", "decimals": 2 },
  ...,
  "currentState": {
    "status": "FAILED",
    "reason": {
      "code": "INVALID_ACCOUNT",
      "message": "Invalid account.",
      ...
    },
    ...
  },
  ...
}
```

The webhook is terminal; no further events fire for this operation. Cycle through the six magic cents values to exercise six independent rail-error branches of your handler without re-registering beneficiaries.

### Crypto wallet instructions

Crypto wallets are screened against a real chain-analysis provider in both sandbox and production. There is no sandbox-only mock layer. To simulate a rejected beneficiary, send a `paymentInstruction.address` that the provider rejects in the real world: for example, an address with an invalid format or checksum, or a publicly known blocklisted address.

The same submission against production returns the same rejection.

#### Force a custody-attestation document rejection

A crypto beneficiary also submits a **custody attestation** document. Independently of wallet screening, you can reject the beneficiary through its document check by uploading the attestation with a filename that contains the lowercase word `reject`, either inline on [`POST /v1/beneficiaries`](/api-reference/fx-payment/beneficiaries/create-beneficiary) or via [`POST /v1/beneficiaries/{beneficiaryId}/documents`](/api-reference/fx-payment/beneficiaries/submit-beneficiary-document).

| Uploaded filename                     | Outcome                                                                                                                                                                                                                                                                                                |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `reject.pdf`, `custody-reject.png`, … | The custody-attestation check fails and the instruction is rejected; [`BENEFICIARY_PAYMENT_INSTRUCTION_REJECTED`](/api-reference/fx-webhook/events/beneficiary/beneficiary-payment-instruction-rejected) fires after the review settles, with the reason on `instruction.currentState.reason.message`. |

Put `reject` in the file's name, not its extension, and keep the letters together; a space or symbol between them (`rej ect`) breaks the match. Any other filename follows the normal screening path.

## Deposits

In sandbox, the deposit amount decides its QR code's outcome:

| Deposit amount (`sourceAmount`) | Outcome                   |
| ------------------------------- | ------------------------- |
| `8.00`                          | The QR code is never paid |
| `9.00`                          | The QR code expires       |
| Any other amount                | The QR code is paid       |

## Crypto test tokens

The sandbox uses a fixed set of test tokens for crypto deposits, swaps, and withdrawals. These are mock ERC-20 contracts that Trace Finance controls. They mirror the shape of the real assets but hold no monetary value, so you can move them freely during homologation.

<Warning>
  Everything in the sandbox runs on the **Ethereum testnet (Sepolia)**, never on mainnet. The API always reports the network as `ETHEREUM`, the same value it uses in production, but in the sandbox that value resolves to Sepolia. The contract addresses below are Sepolia deployments and carry no value. Never treat them as the real `USDT`, `USDC`, or `BRL` tokens.
</Warning>

<Note>
  Only the **`ETHEREUM`** network is available in the sandbox today. Other networks are not yet supported for sandbox testing.
</Note>

| Name              | `symbol` | `network`                    | `contractAddress`                            | `decimals` |
| ----------------- | -------- | ---------------------------- | -------------------------------------------- | ---------- |
| Trace Finance BRL | `BRLT`   | `ETHEREUM` (Sepolia testnet) | `0x2588a80f342ea4f24c91c0148a3d6e832ce9dca9` | 6          |
| Trace Mock USDT   | `USDT`   | `ETHEREUM` (Sepolia testnet) | `0x164afc6456b21b4b1bd505a69be35cc2d9692fd8` | 6          |
| Trace Mock USDC   | `USDC`   | `ETHEREUM` (Sepolia testnet) | `0xca732283fd24c588d9084b1ae357b540e9e7b2f3` | 6          |

## Related

* [Environments](/guides/environments) — sandbox and production base URLs
* [Crypto assets and networks](/guides/crypto-assets) — production stablecoins, networks, and contract addresses
* [Beneficiaries](/guides/compliance/beneficiaries) — what gets screened and what stays on your side
* [Register a beneficiary](/journeys/register-beneficiary) — step-by-step procedure for submitting beneficiaries and payment instructions
* [Deposit](/journeys/deposit) — end-to-end deposit with a PIX dynamic QR code
* [Test webhooks in sandbox](/webhooks/test-in-sandbox) — develop and verify webhook handlers
