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

# Pay-in: BRL to USDC

> Receive a Pix payment in BRL and deliver it as USDC to your customer's wallet, end to end in the sandbox.

A pay-in takes fiat from a payer and delivers stablecoin to your customer. In this quickstart, a payer sends 1,000 BRL over Pix and your customer receives the equivalent in USDC on Polygon. It runs in the sandbox, where verification and the Pix payment are simulated, so it takes a few minutes and no real money moves.

## Why BRL and USDC

The example uses Brazil because Pix settles instantly and the sandbox simulates it from start to finish. USDC is a dollar stablecoin, so your customer ends up holding dollars on-chain: think of a Brazilian client paying an invoice in reais while your customer keeps the proceeds in dollars.

The same calls work in other corridors. Change the currency in `accounts`, the `rail`, and `sourceCurrency`, for example `MXN` over `SPEI`. See [Coverage](https://docs.lumx.io/get-started/coverage.md) for every currency, rail, and network.

## Build it with your AI agent

Copy a prompt into Cursor, Claude Code, Codex, or any coding agent. Both read this page and the API spec before writing code.

> [tab] Build it for me
>
> The agent writes and runs the full script, then reports back.
>
> ```text Prompt theme={null}
> You are a backend engineer integrating Lumx. Goal: in the Lumx sandbox, receive a BRL payment over Pix and deliver it as USDC to a customer's wallet, end to end, in one script.
>
> Ground truth. Read these before writing code and follow them over any prior knowledge:
> 1. https://docs.lumx.io/quickstarts/pay-in.md, the quickstart you are implementing.
> 2. https://docs.lumx.io/llms.txt, the documentation index. Every page has a .md twin at its own path.
> 3. https://lumx-docs-public-prod.s3.us-east-1.amazonaws.com/api-production.yaml, the OpenAPI spec. Take field names and enum values from here.
>
> Use https://api-sandbox.lumx.io only. Read the API key from the LUMX_API_KEY environment variable and never hard-code it. Never call production.
>
> Steps:
> 1. POST /customers: an INDIVIDUAL with accounts ["BRL"] and a valid CPF as taxId whose last digit is not 1, 2, or 3. In the sandbox, that last digit sets the verification outcome, and any other digit approves.
> 2. POST /customers/{id}/tos with the body {}. A POST without a body is rejected with 411. In the sandbox, this approves the customer.
> 3. Poll GET /accounts?customerId={id} until the BRL account is ACTIVE.
> 4. POST /transactions/on-ramp with rail PIX, sourceCurrency BRL, sourceAmount "1000.00", targetCurrency USDC, purpose PERSONAL_ACCOUNT, blockchain POLYGON, and an Idempotency-Key header.
> 5. Poll GET /transactions/{id} until the status is SUCCESS or FAILED. Print finalTargetAmount and blockExplorerUrl from the receipt.
>
> Constraints:
> - Retry 429 responses with exponential backoff. No rate limit is published, so do not assume one.
> - Exit non-zero if any step fails, and log what each step returned.
>
> When you finish, hand back the script and a short summary of each step's result.
> ```

> [tab] Step by step
>
> The agent explains each call and waits for your go-ahead before running it.
>
> ```text Prompt theme={null}
> You are a backend engineer teaching me to integrate Lumx. Goal: in the Lumx sandbox, receive a BRL payment over Pix and deliver it as USDC to a customer's wallet. Walk me through it one step at a time.
>
> Ground truth. Read these first and follow them over any prior knowledge:
> 1. https://docs.lumx.io/quickstarts/pay-in.md, the quickstart we are following.
> 2. https://docs.lumx.io/llms.txt, the documentation index. Every page has a .md twin at its own path.
> 3. https://lumx-docs-public-prod.s3.us-east-1.amazonaws.com/api-production.yaml, the OpenAPI spec.
>
> Use https://api-sandbox.lumx.io only. Read the API key from the LUMX_API_KEY environment variable and never print it. Never call production.
>
> For each step: explain what the call does and why it is needed, show the exact request, run it only after I confirm, then show the response and point out the fields we use next. If a call fails, stop and explain the error before trying anything else.
>
> Steps:
> 1. POST /customers: an INDIVIDUAL with accounts ["BRL"] and a valid CPF as taxId whose last digit is not 1, 2, or 3.
> 2. POST /customers/{id}/tos with the body {}. In the sandbox, this approves the customer.
> 3. GET /accounts?customerId={id} until the BRL account is ACTIVE.
> 4. POST /transactions/on-ramp with rail PIX, sourceCurrency BRL, sourceAmount "1000.00", targetCurrency USDC, purpose PERSONAL_ACCOUNT, blockchain POLYGON, and an Idempotency-Key header.
> 5. GET /transactions/{id} until the status is SUCCESS, then walk me through the receipt.
> ```

## How it works

| **Object** | **Role in the pay-in** |
| :- | :- |
| [Customer](https://docs.lumx.io/concepts/customers.md) | The person or company you serve. It has to be approved before money moves. |
| [Account](https://docs.lumx.io/concepts/accounts.md) | A BRL account in the customer's name. The Pix payment lands here. |
| [On-ramp](https://docs.lumx.io/concepts/transactions.md) | One conversion: how much BRL comes in, over which rail, and which stablecoin goes out. It returns the Pix code to pay. |
| [Wallet](https://docs.lumx.io/concepts/wallets.md) | Created with the customer. It receives the USDC. |

## Before you start

* A sandbox API key. See [Authentication](https://docs.lumx.io/get-started/authentication.md).
* The sandbox base URL, `https://api-sandbox.lumx.io`. See [Environments](https://docs.lumx.io/get-started/environments.md).

## 1. Create a customer with a BRL account

Every pay-in belongs to a customer, and the BRL has to land in an account in that customer's name. Create both in one call: `accounts` lists the currencies to open.

```bash Request theme={null}
curl -X POST https://api-sandbox.lumx.io/customers \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "INDIVIDUAL",
    "name": "Ana Souza",
    "taxId": "529.982.247-25",
    "birthDate": "1990-01-01",
    "country": "BRA",
    "email": "ana.souza@example.com",
    "accounts": ["BRL"]
  }'
```

```json Response (excerpt) theme={null}
{
  "id": "9d1ed178-7c29-42bb-912f-255f0e10cdb9",
  "type": "INDIVIDUAL",
  "name": "Ana Souza",
  "accounts": [
    { "id": "2966586d-8f2f-43c8-b655-e2524d3d886b", "currency": "BRL" }
  ],
  "verification": { "status": "NOT_STARTED", "level": "STANDARD" }
}
```

Save the customer `id`. In the sandbox, the last digit of `taxId` sets the verification outcome, and a `taxId` that ends in `5` is approved. See [Sandbox magic numbers](https://docs.lumx.io/compliance/identity-verification.md#sandbox-magic-numbers).

## 2. Request the terms of service link

A customer has to accept the Lumx terms of service before verification can start.

```bash Request theme={null}
curl -X POST https://api-sandbox.lumx.io/customers/9d1ed178-7c29-42bb-912f-255f0e10cdb9/tos \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```json Response theme={null}
{
  "url": "https://dashboard.lumx.io/tos/sandbox/eyJhbGciOiJSUzI1NiIs...",
  "expiresAt": "2026-11-10T02:17:33Z"
}
```

Send `{}` as the body. A `POST` without a body is rejected with `411`. In the sandbox, the customer moves to `APPROVED` as soon as you request the link.

## 3. Wait for the BRL account to be active

The account can only receive money once it is `ACTIVE`. After the customer is approved, it goes through `REQUESTED` and `PROVISIONING` to `ACTIVE`. In the sandbox this takes about a minute.

```bash Request theme={null}
curl "https://api-sandbox.lumx.io/accounts?customerId=9d1ed178-7c29-42bb-912f-255f0e10cdb9" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json Response (excerpt) theme={null}
{
  "data": [
    {
      "id": "2966586d-8f2f-43c8-b655-e2524d3d886b",
      "customerId": "9d1ed178-7c29-42bb-912f-255f0e10cdb9",
      "status": "ACTIVE",
      "currency": "BRL"
    }
  ]
}
```

## 4. Create the on-ramp

The on-ramp says what you expect to receive and what to deliver: 1,000 BRL over Pix, converted to USDC on Polygon. Polygon is one of several supported networks, and `blockchain` picks it.

```bash Request theme={null}
curl -X POST https://api-sandbox.lumx.io/transactions/on-ramp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "customerId": "9d1ed178-7c29-42bb-912f-255f0e10cdb9",
    "rail": "PIX",
    "sourceCurrency": "BRL",
    "sourceAmount": "1000.00",
    "targetCurrency": "USDC",
    "purpose": "PERSONAL_ACCOUNT",
    "blockchain": "POLYGON"
  }'
```

```json Response theme={null}
{
  "id": "07a8928a-0617-4858-a75c-45fc034f3377",
  "customerId": "9d1ed178-7c29-42bb-912f-255f0e10cdb9",
  "type": "ON_RAMP",
  "request": {
    "sourceCurrency": "BRL",
    "targetCurrency": "USDC",
    "sourceAmount": "1000.00",
    "rail": "PIX",
    "purpose": "PERSONAL_ACCOUNT",
    "blockchain": "POLYGON"
  },
  "state": {
    "status": "AWAITING_FUNDS",
    "payment": {
      "rail": "PIX",
      "brCode": "00020126580014br.gov.bcb.pix0136...6304"
    }
  },
  "metadata": {},
  "createdAt": "2026-11-03T02:18:37.644Z",
  "updatedAt": "2026-11-03T02:18:37.644Z"
}
```

* `state.payment.brCode` is the Pix code the payer pays. In the sandbox, the payment is simulated and the on-ramp continues on its own.
* The `Idempotency-Key` header makes a retried request safe: the same key never creates a second on-ramp. See [Idempotency](https://docs.lumx.io/developer/idempotency.md).
* `purpose` declares why the money moves. `PERSONAL_ACCOUNT` fits a customer funding their own wallet. See [Purpose codes](https://docs.lumx.io/additional-information/purpose-codes.md).

## 5. Wait for the USDC

The on-ramp moves through `TRADING` and `TRANSFERRING_STABLECOIN` to `SUCCESS`. In the sandbox this takes about a minute.

```bash Request theme={null}
curl https://api-sandbox.lumx.io/transactions/07a8928a-0617-4858-a75c-45fc034f3377 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json Response (excerpt) theme={null}
{
  "id": "07a8928a-0617-4858-a75c-45fc034f3377",
  "type": "ON_RAMP",
  "state": {
    "status": "SUCCESS",
    "receipt": {
      "sourceCurrency": "BRL",
      "sourceAmount": "1000.00",
      "targetCurrency": "USDC",
      "baseExchangeRate": "0.183915",
      "baseTargetAmount": "183.914825",
      "fees": {
        "lumx": { "rate": "5", "flatAmount": "1.000000", "totalAmount": "1.091957", "currency": "USDC" }
      },
      "finalTargetAmount": "182.822867",
      "finalExchangeRate": "0.182823",
      "transactionHash": "0xfb7a55d3307d8ca3a02a9980103a5238949f52c26d1abb90a3ed8e05c914fd4a",
      "blockExplorerUrl": "https://amoy.polygonscan.com/tx/0xfb7a55d3307d8ca3a02a9980103a5238949f52c26d1abb90a3ed8e05c914fd4a"
    }
  }
}
```

The receipt shows the conversion. `baseTargetAmount` is the USDC before fees, `fees` breaks them down, and `finalTargetAmount` is what reached the customer's wallet. `blockExplorerUrl` opens the on-chain transfer.

The customer now holds USDC. Pay it out in the [payout quickstart](https://docs.lumx.io/quickstarts/payout.md).

## What changes in production

* **Verification:** your customer opens the terms of service link and completes KYC or KYB. See [Individual Verification](https://docs.lumx.io/guides/individual-verification.md) and [Business Verification](https://docs.lumx.io/guides/business-verification.md).
* **The payment:** the payer pays the `brCode` from any Pix app. If nobody pays within the payment window, the on-ramp expires. See [Transactions](https://docs.lumx.io/concepts/transactions.md#payment-expiration).
* **Status updates:** subscribe to the `account.active` and `onramp.*` [webhooks](https://docs.lumx.io/developer/webhooks.md) instead of polling.
* **Recurring deposits:** to convert every deposit into an account without one call per payment, use an [autoconversion rule](https://docs.lumx.io/guides/autoconversion-rules.md).

## Related resources

> [card] [Payout: USDC to BRL](https://docs.lumx.io/quickstarts/payout.md)
>
> Pay the USDC out to a Pix key.

> [card] [Autoconversion rules](https://docs.lumx.io/guides/autoconversion-rules.md)
>
> Convert every deposit automatically, with no call per payment.

> [card] [Collect BRL via Pix](https://docs.lumx.io/guides/use-cases/collect-brl-via-pix-settle-in-stablecoins.md)
>
> The full pay-in guide, with locked rates and webhooks.

> [card] [Coverage](https://docs.lumx.io/get-started/coverage.md)
>
> Every currency, rail, and network you can swap in.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.