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

# API conventions

> Rules that apply to every endpoint of the LB Pay Cross-Border Payouts API: authentication, amounts, pagination, errors and webhook signatures.

## Authentication

Every endpoint requires a bearer token (`Authorization: Bearer <token>`), except `GET /v1/health`.

## Principles

* Quote and operation are separate. The quote (`POST /v1/fx/quotes`) is only a price and does not create a remittance. The remittance is created by the operation you want to perform; in v1, a withdrawal to a beneficiary: `POST /v1/fx/quotes` → `POST /v1/remittances/withdrawals`.
* A quote is only a price: one price, the same for `PREFUNDED` and `CREDIT`, valid for any of your senders. The only remittance fee is the FX spread, as a percentage. The advance cost (`CREDIT`) follows your agreement and is charged in the settlement batch. Sender, beneficiary, purpose and funding are informed in the withdrawal.
* USDC Inventory: you can contract FX in advance. A quote with `usage = INVENTORY` is used once to create an Inventory Lot (`POST /v1/inventories`), which locks rate, volume and validity and creates the USDC payment promise. The lot is then used by withdrawals with `funding.mode = INVENTORY`. See [USDC Inventory](https://developers.javalibridge.com/en/guides/inventory.md).
* Monetary amounts are decimal strings. Request amounts must be greater than zero.
* Lists use cursor pagination (`cursor`, `limit`; the response has `nextCursor`).

## Rate limiting

`429` responses carry `Retry-After` (seconds). Respect the header and apply exponential backoff with jitter.

## Errors

Every error returns `ApiError`. The `code` field follows the catalog below. New codes can be added without a version change, so treat unknown codes by their HTTP status.

| Code | HTTP | Retryable | Description |
| - | - | - | - |
| `VALIDATION_ERROR` | 400 | No | Invalid payload; see `details` for each field. |
| `UNAUTHORIZED` | 401 | No | Missing or invalid credential. |
| `FORBIDDEN` | 403 | No | The credential is not allowed to perform the operation. |
| `NOT_FOUND` | 404 | No | The resource does not exist in your account. |
| `IDEMPOTENCY_CONFLICT` | 409 | No | Same `Idempotency-Key` with a different payload. |
| `QUOTE_EXPIRED` | 409 | No | The quote expired; request a new one. |
| `QUOTE_ALREADY_USED` | 409 | No | The quote was already used by another remittance. |
| `DUPLICATE_EXTERNAL_ID` | 409 | No | `externalId` already used by another of your remittances. |
| `AMOUNT_BELOW_MINIMUM` | 422 | No | Amount below the minimum per transaction (`GET /v1/limits`). |
| `AMOUNT_ABOVE_LIMIT` | 422 | No | Amount above the maximum per transaction (`GET /v1/limits`). |
| `FUNDING_MODE_NOT_ENABLED` | 422 | No | The funding mode is not enabled for your account. |
| `CREDIT_LIMIT_EXCEEDED` | 422 | No | Not enough credit limit available. |
| `INSUFFICIENT_PREFUNDED_BALANCE` | 422 | No | Not enough prefunded USD balance in the US. |
| `SENDER_NOT_ELIGIBLE` | 422 | No | The sender does not exist, has no level to transact or has a restrictive status. Checked in the withdrawal. |
| `ACCOUNT_DAILY_LIMIT_EXCEEDED` | 422 | No | The amount exceeds the daily limit available for your account. |
| `SENDER_LIMIT_EXCEEDED` | 422 | No | The amount exceeds the sender limit in the window (24h/30d/180d). Checked in the withdrawal. |
| `BENEFICIARY_LIMIT_EXCEEDED` | 422 | No | The amount exceeds the beneficiary receiving limit in the window (24h/30d/180d). |
| `BENEFICIARY_NOT_ELIGIBLE` | 422 | No | The beneficiary is not `ACTIVE`. |
| `RELATIONSHIP_MISMATCH` | 422 | No | `senderRelationship` does not match the beneficiary `relationshipType` (`SELF_OWNED` requires `SELF`; `THIRD_PARTY` does not accept `SELF`). |
| `PAYMENT_INSTRUCTION_INVALID` | 422 | No | The payment instruction does not exist, is not `APPROVED` or is ambiguous. |
| `PIX_KEY_NOT_FOUND` | 422 | No | The Pix key does not exist when the withdrawal is created. The key holder is checked before the Pix. |
| `QUOTE_USAGE_MISMATCH` | 422 | No | Quote used in the wrong operation (`INVENTORY` in a withdrawal, or `REMITTANCE` in `POST /v1/inventories`). |
| `DUPLICATE_INVENTORY_EXTERNAL_ID` | 409 | No | `externalId` already used by another of your Inventory Lots. |
| `INVENTORY_NOT_FOUND` | 422 | No | The Inventory Lot in the withdrawal does not exist in your account. A lot from another account returns the same error, without revealing it exists. |
| `INVENTORY_EXPIRED` | 422 | No | The Inventory Lot is past its validity (`EXPIRED`). |
| `INSUFFICIENT_INVENTORY_BALANCE` | 422 | No | Available volume in the Inventory Lot is lower than `destinationAmount`. Another lot is never used automatically. |
| `RATE_LIMITED` | 429 | Yes | Request limit exceeded; respect `Retry-After`. |
| `INTERNAL_ERROR` | 500 | Yes | Unexpected error; retry with the same `Idempotency-Key`. |
| `SERVICE_UNAVAILABLE` | 503 | Yes | Pricing or processing temporarily unavailable, including maintenance (see `GET /v1/health`). |

## Webhook deliveries

The events are listed in [Notifications (webhooks)](https://developers.javalibridge.com/en/guides/webhooks.md). Each delivery is a `POST` with a `WebhookEvent` envelope and these headers:

* `LBPay-Event-Id`: same as `eventId`. Use it to deduplicate; delivery is at-least-once.
* `LBPay-Timestamp`: Unix epoch (seconds) of the delivery.
* `LBPay-Signature`: `v1=<hex(HMAC-SHA256(signingSecret, timestamp + "." + rawBody))>`. Reject the delivery if the signature does not match or if the difference between now and the timestamp is greater than 300 seconds.

Respond with `2xx` within 10 seconds. Failures are retried with exponential backoff for up to 24 hours. Delivery order is not guaranteed: use `occurredAt` and the state of the resource, or fetch the resource with `GET`.

## Reconciliation keys

Every remittance can be traced by the same keys in every object: `externalId` (your ID, unique in your account and immutable), `quoteId`, `remittanceId`, `settlementId` (`CREDIT`), `transactionId` (Pix payment) and `inventoryId` (`INVENTORY`).

* Quote → `remittanceId`, `externalId` (filled in when the quote is used by a withdrawal)
* Remittance → `externalId`, `quoteId` (null in `INVENTORY`), `inventoryId` (`INVENTORY`), `settlement.settlementId`, `payout.transactionId`
* Inventory → `quoteId` (the quote that created the lot), `externalId`; the lot's remittances in `GET /v1/remittances?inventoryId=`
* SettlementItem → `remittanceId`, `externalId`, `quoteId`, `transactionId`
* WalletTransaction → `remittanceId`, `externalId`, `quoteId`, `settlementId`
* Receipt → `remittanceId`, `externalId`, `quoteId`, `transactionId`
* Remittance webhooks → full `Remittance` snapshot


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