> ## 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.

# Treasury management

> Hold working capital in stablecoin, sweep funds between entities, and settle to local fiat on demand

Build a treasury product for corporate customers that need to hold working capital across multiple currencies, sweep funds between related entities, and execute FX conversions on demand. Balances are centralized in stablecoin in each entity's wallet, and converted to local fiat only when needed.

## Step 1: Generate your API key

Head over to [dashboard.lumx.io](https://dashboard.lumx.io). Once logged in, generate a new API key and store it securely. See [Authentication](/get-started/authentication) for details.

## Step 2: Onboard the corporate with multi-currency accounts

Create a business customer for the entity that will hold the treasury. Provision the fiat accounts they need so incoming deposits are converted to stablecoin and consolidated in the customer's wallet automatically. See [Coverage](/get-started/coverage) for supported currencies and rails.

```bash Request theme={null}
curl -X POST https://api-sandbox.lumx.io/customers \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "type": "BUSINESS",
    "legalName": "Acme Holdings Ltd.",
    "taxId": "123456-7",
    "incorporationDate": "2019-01-15",
    "country": "CYM",
    "email": "treasury@acme.com",
    "accounts": ["USD", "EUR", "BRL", "MXN"]
  }'
```

Before the corporate can transact, they must accept Lumx's terms of service (`POST /customers/{id}/tos`) and complete KYB. See [Business verification](/guides/business-verification) for the full onboarding flow.

## Step 3: Fund the corporate's wallet

Once each account is `ACTIVE`, create an on-ramp transaction for every expected deposit, passing the exact amount the corporate plans to fund. The response returns rail-specific payment details in `state.payment`. Share them with the corporate's treasury team; when the deposit matches the amount, Lumx converts the fiat to stablecoin and consolidates it in the customer's wallet.

```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": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "rail": "FEDWIRE",
    "sourceCurrency": "USD",
    "sourceAmount": "1000000.00",
    "targetCurrency": "USDC",
    "purpose": "PERSONAL_ACCOUNT"
  }'
```

<Info>
  Each deposit must be matched to an on-ramp transaction created in advance with the exact amount.
</Info>

All deposits land as stablecoin in the same wallet. The corporate doesn't hold separate per-currency balances. If the corporate already holds stablecoin on-chain, they can also transfer it directly to the wallet returned at customer creation, no on-ramp needed.

Subscribe to the `onramp.success` webhook to know the moment the wallet is credited and balances are ready to be moved or converted. For the full deposit flow by rail, see [Global accounts](/guides/use-cases/global-accounts).

## Step 4: Onboard subsidiaries and counterparty destinations

How you model the corporate group depends on whether each entity needs its own wallet.

Multi-entity (each subsidiary holds its own balance): onboard each subsidiary as its own business customer. Each gets a dedicated wallet, and you can move funds between them with internal transfers.

Single-entity (parent holds all balances): register each related external destination under the parent customer with the appropriate `holder.relationship` so transfers out are correctly categorized.

| **Relationship**     | **Use when**                                                     |
| :------------------- | :--------------------------------------------------------------- |
| `SELF`               | The destination belongs to the same legal entity as the customer |
| `HOLDING_COMPANY`    | The destination belongs to the parent of the customer            |
| `SUBSIDIARY_COMPANY` | The destination belongs to a subsidiary of the customer          |

The `taxId` format varies by jurisdiction; see [Tax IDs by country](/additional-information/tax-ids-by-country) for the expected value per country.

```bash Register a subsidiary's destination under the parent theme={null}
curl -X POST https://api-sandbox.lumx.io/destinations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "customerId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "name": "Acme US - Operations",
    "rail": "FEDWIRE",
    "currency": "USD",
    "identifier": {
      "type": "CHECKING",
      "accountNumber": "123456789012",
      "routingNumber": "021000021"
    },
    "bank": {
      "name": "JPMorgan Chase Bank",
      "address": {
        "line1": "383 Madison Avenue",
        "city": "New York",
        "state": "NY",
        "postalCode": "10179",
        "country": "USA"
      }
    },
    "holder": {
      "type": "BUSINESS",
      "relationship": "SUBSIDIARY_COMPANY",
      "legalName": "Acme US Inc.",
      "taxId": "12-3456789",
      "incorporationDate": "2020-03-15",
      "email": "us@acme.com",
      "address": {
        "line1": "100 Wall Street",
        "city": "New York",
        "state": "NY",
        "postalCode": "10005",
        "country": "USA"
      }
    }
  }'
```

See [Destinations](/concepts/destinations) for all supported rails and the full holder schema.

## Step 5: Move funds between entities

When subsidiaries are onboarded as separate customers, move stablecoin between their wallets without going through fiat. Transfers settle in seconds and don't incur FX cost.

```bash Request theme={null}
curl -X POST https://api-sandbox.lumx.io/transactions/transfer \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "from": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "to": "980dc26b-42fd-4044-8a42-2271d20a2eb9",
    "currency": "USDC",
    "amount": "100000.000000",
    "metadata": {
      "memo": "Q2 working capital injection - Acme US"
    }
  }'
```

```json Response theme={null}
{
  "id": "123e4567-e89b-12d3-a456-426614174004",
  "type": "TRANSFER",
  "state": { "status": "PENDING" },
  "request": {
    "currency": "USDC",
    "from": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "to": "980dc26b-42fd-4044-8a42-2271d20a2eb9",
    "amount": "100000.000000"
  }
}
```

## Step 6: Convert balances to fiat on demand

When the corporate needs to settle in fiat (paying a supplier, repatriating profits, funding a subsidiary's local account), create an off-ramp transaction debiting the wallet. Use the purpose code that matches the move:

| **Scenario**                                       | **Purpose**                                                                 |
| :------------------------------------------------- | :-------------------------------------------------------------------------- |
| Sweep to the entity's own external account         | `PERSONAL_ACCOUNT` (requires a destination with `SELF` holder relationship) |
| Loan or capital injection between related entities | `LOAN`                                                                      |
| Cross-border supplier or invoice payment           | `TRADE_TRANSACTIONS`                                                        |
| Tax remittance                                     | `TAX`                                                                       |
| Bill payment                                       | `BILLS`                                                                     |

See [Purpose codes](/additional-information/purpose-codes) for the full list and rules.

```bash Request theme={null}
curl -X POST https://api-sandbox.lumx.io/transactions/off-ramp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "destinationId": "e80d3137-eddd-4791-b9b8-6e36b289f284",
    "sourceCurrency": "USDC",
    "sourceAmount": "50000.00",
    "purpose": "LOAN"
  }'
```

<Tip>
  For predictable FX (budgeting, monthly settlements, locked supplier quotes), fetch a locked exchange rate first and pass its `id` as `exchangeRateId` on the off-ramp request. See [Exchange Rates](/concepts/exchange-rates).
</Tip>

## Step 7: Track and reconcile

Subscribe to `offramp.success`, `offramp.failed`, `transfer.success`, and `account.active` webhooks to keep balances, transfers, and conversion status in sync inside your product. See [Webhooks](/developer/webhooks).

## Related resources

<CardGroup cols="2">
  <Card title="Global accounts" href="/guides/use-cases/global-accounts">
    Provision multi-currency virtual accounts.
  </Card>

  <Card title="Exchange Rates" href="/concepts/exchange-rates">
    Lock FX rates for predictable conversions.
  </Card>

  <Card title="Destinations" href="/concepts/destinations">
    Holder relationships for inter-company moves.
  </Card>

  <Card title="Transactions" href="/concepts/transactions">
    Transfer, off-ramp lifecycle and purpose codes.
  </Card>
</CardGroup>
