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

# Stablecoin Exchange API

> Reference for 10 Stablecoin Exchange endpoints: exchange rates and quotes, fiat deposits, and conversion transfers.

Version: v1.0 (2026-09-29) · Base URL: `https://api.stablepay.co` · Prefix: `/api/v1` · HTTPS / JSON / UTF-8

## Overview and Scope

The Stablecoin Exchange API covers exchange rates and quotes, fiat deposits that fund conversions, and three conversion flows: fiat to stablecoin, stablecoin to fiat, and stablecoin swaps including cross-chain, together with matching event delivery by webhook. Every path is prefixed with /api/v1. The merchant is determined by the credentials: merchant apps omit `merchant_id`, while service-provider apps use it to target a merchant.

| Method | Path | Purpose |
| :- | :- | :- |
| GET | [`/quote/pairs`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-quote-pairs) | List supported currency pairs |
| GET | [`/quote/exchange_rate`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-quote-exchange-rate) | Retrieve the current pair rate |
| POST | [`/quote`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/post-quote) | Create a quote and lock a rate |
| GET | [`/quote/{quote_id}`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-quote-quote-id) | Retrieve a quote |
| GET | [`/fiat/account_details`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-fiat-account-details) | Retrieve fiat collection details and reference code |
| GET | [`/fiat/deposits`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-fiat-deposits) | List fiat deposit records |
| GET | [`/fiat/deposits/{fiat_deposit_id}`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-fiat-deposits-fiat-deposit-id) | Retrieve one fiat deposit |
| GET | [`/fiat/deposit_balance`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-fiat-deposit-balance) | Convertible fiat deposit balance |
| POST | [`/transfer`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/post-transfer) | Create a transfer (fiat to stablecoin, stablecoin to fiat, stablecoin swap) |
| GET | [`/transfer/{transfer_id}`](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/get-transfer-transfer-id) | Retrieve a transfer |

Amounts are integers in the smallest ledger unit, and fiat, USDT, and USDC all use 2 decimals; rates are decimal strings. Recipients, source accounts, and destination accounts referenced by transfers belong to the Global Accounts capabilities.

## Authentication and Signing

Every request carries an API Key plus the three signing headers, following the common StablePay authentication specification.

| Header | Required | Description |
| :- | :- | :- |
| Authorization | Yes | Bearer `{api_key}` |
| `X-StablePay-Timestamp` | Yes | Unix seconds; within 5 minutes of server time |
| `X-StablePay-Nonce` | Yes | Anti-replay random string, 16 to 64 characters, unique per request |
| `X-StablePay-Signature` | Yes | HMAC-SHA256 signature, lowercase hex |

The signing payload is `{timestamp}.{nonce}.{requestBody}`. GET and DELETE have no body, so `{requestBody}` is an empty string and the payload ends with a dot; POST and PUT sign the exact raw JSON string that is sent, so never reformat or reorder fields after signing. See Pre-integration Preparation for the full algorithm and multi-language samples.

Credentials belong to an app. A merchant app maps to a single merchant and omits `merchant_id`; a service-provider app serves multiple merchants after authorization and passes `merchant_id` in the query or body of quote, fiat deposit, transfer, and recipient endpoints to target a merchant. An unauthorized or inaccessible merchant returns 403 `permission_denied`. Keep the signing secret on the server, and always regenerate the timestamp and nonce when retrying.

## Data Conventions

| Item | Convention | Example |
| :- | :- | :- |
| Resource IDs | `xxx_id` values are 10-digit strings: `merchant_id`, `fiat_deposit_id`, `quote_id`, `recipient_id`, `transfer_id`, `event_id`, `request_id` | "9000000070" |
| Account number | `account_no`. Account query endpoints return an 8-digit string; fund endpoint examples use the 00000001 form. Always use the value actually returned and never validate against a fixed pattern | "00000001", "00000001" |
| Amount | Integer in the smallest unit of the currency; fiat and USDT/USDC all use 2 decimals | 1050 means 10.50 USD; 125000 means 1,250.00 USDC |
| Currency | Uppercase; ISO 4217 for fiat, asset code for stablecoins | USD, SGD, USDT, USDC |
| Network | ethereum, tron, solana, base, polygon, arbitrum, bsc | solana |
| Time | Unix seconds as an integer | 1718726400 |
| Ratios | Exchange rates and similar ratios are decimal strings, never floats | "0.9998" |
| Empty fields | Optional fields that do not apply are omitted | — |

List endpoints use cursor pagination: limit defaults to 20 and caps at 100, the response returns `next_cursor`, and the last page omits it. The account query endpoints are the exception: the account list returns every account at once with no pagination or filters.

Create endpoints support two idempotency mechanisms: the `Idempotency-Key` header, and the `external_xxx_id` body field, which together with `merchant_id` forms a per-merchant unique key. Reusing a key with different parameters returns 409 `idempotency_conflict`; reuse the same identifier when retrying after a timeout.

## Events

Events record state changes across all merchant resources and are delivered to the merchant webhook endpoint. The event query endpoints are not publicly available; rely on webhook payloads together with transfer and quote queries for reconciliation.

### Event Types

| Event | Description |
| :- | :- |
| `fiat_deposit.credited` | Fiat deposit credited; data is the fiat deposit record |
| quote.created / used / expired | Quote lifecycle |
| transfer.processing / `payment_submitted` / completed / `funds_refunded` / `bounced_back` | Transfer lifecycle |

Webhook requests carry `X-StablePay-Event-Type` and `X-StablePay-Event-ID`. Failed deliveries retry up to 10 times with exponential backoff starting at 2 minutes and capping at 1024 minutes. The same event may be delivered more than once, so deduplicate by `X-StablePay-Event-ID` and confirm final state with transfer and quote queries.

## Errors and Status Codes

Errors use a shared envelope: an error object (type, code, message, param), plus `request_id` and timestamp. Include `request_id` when reporting an issue.

Example error response

```json theme={"system"}
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_parameter",
    "message": "The amount must be greater than zero.",
    "param": "amount"
  },
  "request_id": "9000000099",
  "timestamp": 1718726400
}
```

| Status | Code | Meaning |
| :- | :- | :- |
| 400 | `invalid_parameter` | Missing or invalid parameter, such as a zero amount or an unsupported currency or network |
| 401 | `invalid_api_key` | API key missing, invalid, or revoked, or signature verification failed |
| 403 | `permission_denied` | The merchant has not authorized this app, or the app cannot access the target merchant |
| 404 | `resource_not_found` | The resource does not exist or belongs to another merchant |
| 409 | conflict | Business state conflict: `idempotency_conflict`, `insufficient_funds`, `quote_expired`, `quote_not_open` |
| 429 | `rate_limit_exceeded` | Rate limit exceeded; back off and retry |
| 500 | `internal_error` | Platform internal error; contact support with `request_id` |
| 503 | — | Balance query service temporarily unavailable; retry with a new timestamp, nonce, and signature |

error.type is one of `api_error`, `invalid_request_error`, `authentication_error`, `permission_error`, `resource_not_found`, conflict, or `rate_limit_error`. param is returned only when a specific parameter can be identified. Always regenerate the timestamp and nonce on retry, and never blindly retry a 401.

## Handling Error Codes

| Code | Retry | Recommended action |
| :- | :- | :- |
| `invalid_parameter` | No | Fix the parameter named in param; zero amounts and unsupported currencies or networks land here |
| `invalid_api_key` | No | Check the key, the trailing dot in the signing payload, and server clock skew |
| `permission_denied` | No | Service-provider apps should confirm `merchant_id` is within the authorized scope |
| `resource_not_found` | No | Verify the quote, deposit record, transfer, or currency pair exists and belongs to the merchant |
| `idempotency_conflict` | No | Same key with different parameters: reuse the original payload or use a new key |
| `insufficient_funds` | No | Check `available_amount` on the source account |
| `quote_not_open` / `quote_expired` | No | The quote was consumed or expired: create a new quote, or lock the rate inline with `rate_type`=fixed |
| `rate_limit_exceeded` | Yes | Back off and reduce concurrency |
| `internal_error` / 503 | Yes | Retry with a new timestamp, nonce, and signature; if it persists, report with `request_id` |

Conversions move money, so keep the same idempotency identifier on retry and check the transfer status before resubmitting to avoid converting twice.

## Version and Change Log

| Version | Change |
| :- | :- |
| 2026-09-29 | First public version: exchange rates and quotes, fiat deposits, and conversion transfers — 10 endpoints. Events are delivered by webhook; no event query endpoints are provided. |

## API Boundaries

* Account opening, renaming, and merchant administration happen in the merchant dashboard, not through this API.
* The API returns only the current merchant's own accounts and transaction data; cross-merchant queries are not available.
* Cross-merchant transfers and platform account collection are provided by the Payouts product.
* Rate endpoints return the current mid-market rate only and are not a binding quote.
* KYB and KYC submission and review status are not handled by this API.

## Related Documentation

* [Global Accounts Product Documentation](https://docs.stablepayfi.ai/en/product/Global-Accounts.md)
* [Global Accounts API Documentation](https://docs.stablepayfi.ai/en/api/global-accounts/overview)
* [Stablecoin Exchange Product Documentation](https://docs.stablepayfi.ai/en/product/Stablecoin-Exchange.md)
* [Stablecoin Exchange API Documentation](https://docs.stablepayfi.ai/en/api/stablecoin-exchange/overview)
* [Pre-integration Preparation](https://docs.stablepayfi.ai/en/api/getting-started.md)
* [Webhook Notifications](https://docs.stablepayfi.ai/en/api/webhook-notifications.md)


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