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 omitmerchant_id, while service-provider apps use it to target a merchant.
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.
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
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
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), plusrequest_id and timestamp. Include request_id when reporting an issue.
Example error response
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
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
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.
