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

# USDC Inventory

> O USDC Inventory permite que a MSB contrate câmbio antecipadamente, travando taxa e volume em um Inventory Lot, e use esse volume depois em withdrawals. Ao contratar, a MSB assume uma promessa de pagamento em USDC.

> [!NOTE]
>
> A modalidade precisa estar habilitada para a sua conta; caso contrário, a API retorna `FUNDING_MODE_NOT_ENABLED`.

## 1. Cotar com usage = INVENTORY

Solicite a cotação em `POST /v1/fx/quotes` com `usage = INVENTORY` e exatamente um entre `sourceAmount` (USD) e `destinationAmount` (BRL). A resposta traz duas datas: `expiresAt` é a validade da própria cotação; `inventoryExpiresAt` é a validade que o lote terá se for criado.

```http POST /v1/fx/quotes · requisição theme={null}
POST /v1/fx/quotes
Idempotency-Key: 7f1c2a9e-inv-quote
```

```json Corpo da requisição theme={null}
{
  "fromCurrency": "USD",
  "toCurrency": "BRL",
  "sourceAmount": "100000.00",
  "usage": "INVENTORY"
}
```

```json 201 · FxQuote theme={null}
{
  "quoteId": "qt_01JA1X",
  "status": "AVAILABLE",
  "usage": "INVENTORY",
  "fromCurrency": "USD",
  "toCurrency": "BRL",
  "source": {
    "currency": "USD",
    "amount": "100000.00"
  },
  "destination": {
    "currency": "BRL",
    "amount": "540000.00"
  },
  "referenceRate": "5.46558704",
  "rate": "5.40000000",
  "spread": {
    "percentage": "1.2",
    "amount": {
      "currency": "USD",
      "amount": "1200.00"
    }
  },
  "expiresAt": "2026-11-04T14:05:00Z",
  "inventoryExpiresAt": "2026-11-10T23:59:59Z",
  "inventoryId": null,
  "createdAt": "2026-11-04T14:00:00Z"
}
```

## 2. Criar o lote

Chame `POST /v1/inventories` com o `quoteId`. Essa chamada é o aceite: em uma operação a LB Pay fecha com você taxa e volume, cria a promessa de pagamento em USDC e cria o lote, que nasce `ACTIVE`. A cotação passa a `USED` e registra o `inventoryId`. Cada chamada cria um lote novo e independente; lotes nunca são agregados. O lote pode existir sem nenhum withdrawal.

```http POST /v1/inventories · requisição theme={null}
POST /v1/inventories
Idempotency-Key: 7f1c2a9e-inv-create
```

```json Corpo da requisição theme={null}
{
  "quoteId": "qt_01JA1X",
  "externalId": "inventory-2026-11-04-001"
}
```

```json 201 · Inventory theme={null}
{
  "inventoryId": "inv_01JA2B",
  "externalId": "inventory-2026-11-04-001",
  "quoteId": "qt_01JA1X",
  "status": "ACTIVE",
  "fromCurrency": "USD",
  "toCurrency": "BRL",
  "referenceRate": "5.46558704",
  "rate": "5.40000000",
  "spread": {
    "percentage": "1.2",
    "amount": {
      "currency": "USD",
      "amount": "1200.00"
    }
  },
  "total": {
    "source": { "currency": "USD", "amount": "100000.00" },
    "destination": { "currency": "BRL", "amount": "540000.00" }
  },
  "available": {
    "source": { "currency": "USD", "amount": "100000.00" },
    "destination": { "currency": "BRL", "amount": "540000.00" }
  },
  "reserved": {
    "source": { "currency": "USD", "amount": "0.00" },
    "destination": { "currency": "BRL", "amount": "0.00" }
  },
  "used": {
    "source": { "currency": "USD", "amount": "0.00" },
    "destination": { "currency": "BRL", "amount": "0.00" }
  },
  "pendingSettlement": null,
  "settlementId": null,
  "expiresAt": "2026-11-10T23:59:59Z",
  "createdAt": "2026-11-04T14:01:12Z",
  "updatedAt": "2026-11-04T14:01:12Z"
}
```

## 3. Consultar saldos

`GET /v1/inventories/{inventoryId}` retorna taxa, validade e saldos. Todos os saldos aparecem em BRL e USD. O controle é feito em BRL; o USD é calculado na taxa do lote.

| Campo | Significado |
| - | - |
| `total` | Volume contratado |
| `available` | Volume disponível para novos withdrawals |
| `reserved` | Volume reservado por withdrawals em andamento |
| `used` | Volume já utilizado por withdrawals |

> [!NOTE]
>
> `total = available + reserved + used`, sempre.

Exemplo: um lote de USD 100.000,00 à taxa 5,40000000 equivale a BRL 540.000,00. Um withdrawal de BRL 10.000,00 reserva USD 1.851,85 (10.000 ÷ 5,40).

| Momento | available | reserved | used |
| - | - | - | - |
| Lote criado | BRL 540.000,00 · USD 100.000,00 | 0 | 0 |
| Withdrawal reservado | BRL 530.000,00 · USD 98.148,15 | BRL 10.000,00 · USD 1.851,85 | 0 |
| Volume utilizado | BRL 530.000,00 · USD 98.148,15 | 0 | BRL 10.000,00 · USD 1.851,85 |
| Withdrawal `REJECTED` | BRL 540.000,00 · USD 100.000,00 | 0 | 0 |

### Status do lote

| Status | Significado |
| - | - |
| `ACTIVE` | Dentro da validade, com volume disponível. |
| `DEPLETED` | Sem volume disponível (todo reservado ou utilizado). Volta a `ACTIVE` se uma reserva for liberada dentro da validade. |
| `EXPIRED` | Passou de `expiresAt`. Não aceita novos withdrawals. |

## 4. Criar o withdrawal

Crie o withdrawal com `funding.mode = INVENTORY`, `funding.inventoryId`, `destinationAmount` (o BRL que o beneficiário recebe) e `senderQuote`. Não envie `quoteId`. Valores e taxa vêm do lote. A LB Pay confere se o lote existe na sua conta, está dentro da validade e tem BRL disponível suficiente, aplica as validações usuais do [withdrawal](https://developers.javalibridge.com/pt-BR/guides/withdrawal.md) e reserva o volume de forma atômica. Outro lote nunca é usado automaticamente.

| Campo | PREFUNDED / CREDIT | INVENTORY |
| - | - | - |
| `quoteId` | Obrigatório | Não aceito |
| `funding.inventoryId` | Não aceito | Obrigatório |
| `destinationAmount` (BRL) | Não aceito | Obrigatório |
| `senderQuote` | Opcional | Obrigatório |

> [!NOTE]
>
> Violação retorna `VALIDATION_ERROR` (400), com o campo em `details`.

`senderQuote` traz os dados da operação de câmbio da MSB com o remetente: taxa, valores em USD e BRL, horário da cotação e a sua referência. É gravado como recebido e usado na formalização da operação. Não altera os valores da remessa nem a taxa do lote. A estrutura pode receber novos campos.

```http POST /v1/remittances/withdrawals · requisição theme={null}
POST /v1/remittances/withdrawals
Idempotency-Key: 7f1c2a9e-wd-125
```

```json Corpo da requisição theme={null}
{
  "senderId": "snd_789",
  "externalId": "remittance-125",
  "destinationAmount": "10000.00",
  "funding": {
    "mode": "INVENTORY",
    "inventoryId": "inv_01JA2B"
  },
  "beneficiaryId": "ben_125",
  "purpose": "FAMILY_MAINTENANCE",
  "senderRelationship": "FAMILY",
  "senderQuote": {
    "rate": "5.55000000",
    "source": {
      "currency": "USD",
      "amount": "1801.80"
    },
    "destination": {
      "currency": "BRL",
      "amount": "10000.00"
    },
    "quotedAt": "2026-11-04T14:00:00Z",
    "reference": "msb-quote-8812"
  }
}
```

```json 201 · WithdrawalResponse theme={null}
{
  "remittanceId": "rem_01JA3C",
  "type": "WITHDRAWAL",
  "quoteId": null,
  "inventoryId": "inv_01JA2B",
  "senderId": "snd_789",
  "externalId": "remittance-125",
  "status": "PROCESSING",
  "fundingMode": "INVENTORY",
  "message": "Remessa criada; câmbio e Pix ainda não confirmados."
}
```

```json 422 · ApiError theme={null}
{
  "code": "INSUFFICIENT_INVENTORY_BALANCE",
  "message": "Volume disponível no inventory inv_01JA2B é menor que destinationAmount.",
  "requestId": "req_9b1e",
  "retryable": false,
  "details": [
    {
      "field": "destinationAmount",
      "reason": "available BRL 4000.00"
    }
  ]
}
```

## 5. Acompanhar e conciliar

* `inventory.created`: lote criado. `inventory.status_changed`: `ACTIVE` ↔ `DEPLETED`, ou `EXPIRED`. Nos dois, `data.object` é o Inventory.
* Remessas financiadas por um lote seguem os eventos `remittance.*`.
* Mudanças de saldo sem mudança de status não geram evento. Consulte o saldo em `GET /v1/inventories/{inventoryId}`.
* Liste as remessas de um lote com `GET /v1/remittances?inventoryId=`.
* Em uma remessa `INVENTORY`, `quoteId` é null, `inventoryId` identifica o lote e `fx.rate` é a taxa do lote. `fx.status = CONTRACTED` só depois da confirmação da execução. Em `REJECTED`, o volume reservado volta ao lote.

## Erros

| Código | HTTP | Causa | O que fazer |
| - | - | - | - |
| `QUOTE_USAGE_MISMATCH` | 422 | Cotação usada na operação errada: `INVENTORY` em withdrawal, ou `REMITTANCE` em `POST /v1/inventories`. | Solicite uma nova cotação com o `usage` correto. |
| `DUPLICATE_INVENTORY_EXTERNAL_ID` | 409 | `externalId` já usado por outro lote da sua conta. | Use um novo `externalId` ou localize o lote existente com `GET /v1/inventories?externalId=`. |
| `INVENTORY_NOT_FOUND` | 422 | O lote informado em `funding.inventoryId` não existe na sua conta. | Confira o `inventoryId`. Lote de outra conta retorna o mesmo erro. |
| `INVENTORY_EXPIRED` | 422 | O lote está `EXPIRED`. | Use outro lote `ACTIVE` ou contrate um novo. |
| `INSUFFICIENT_INVENTORY_BALANCE` | 422 | O volume disponível no lote é menor que `destinationAmount`. | Consulte o saldo em `GET /v1/inventories/{inventoryId}` antes de tentar de novo. Outro lote nunca é usado automaticamente. |
| `FUNDING_MODE_NOT_ENABLED` | 422 | `INVENTORY` não está habilitado para a sua conta. Vale para a criação do lote e para o withdrawal. | Fale com a LB Pay para habilitar a modalidade. |

> [!TIP]
>
> **Boas práticas**
>
> * Informe sempre o lote explicitamente. A LB Pay nunca usa outro lote automaticamente.
> * Trate `INSUFFICIENT_INVENTORY_BALANCE` consultando o saldo antes de tentar de novo.
> * Use `Idempotency-Key` na criação do lote e no withdrawal.
> * Envie em `senderQuote` os valores reais da operação com o remetente.

## Em definição

> [!WARNING]
>
> Validade e expiração do volume não utilizado, cancelamento de lote e cobrança da obrigação em USDC ainda estão em definição. Essas regras serão comunicadas antes da disponibilidade geral.


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