Endpoints Overview
Get Quote
Generate a price quote by matching your requested cNGN amount against live orderbook liquidity. The response includes the matched order(s), the resulting stablecoin amount you will receive, and aquoteId you can pass directly to POST /fx/trade. The quote is valid for 15 minutes.
Quotes expire exactly 15 minutes after generation, and each
quoteId can be executed only once. If you pass an expired or already-used quoteId to POST /fx/trade, the request is rejected with INVALID_QUOTE. Generate a fresh quote and retry.- Request
- Response
string
required
Trading pair in the format
CNGN-TOKEN. Accepted values: "CNGN-USDC" or "CNGN-USDT".string
required
Trade direction. Use
"sell" to exchange cNGN for the quote currency, or "buy" to acquire cNGN by spending the quote currency.string
The cNGN amount to trade, expressed as a human-readable decimal (e.g.,
"50000" means 50,000 cNGN). Provide this or tokenAmount, not both. Minimum is 1,000 cNGN.string
The pair-currency amount to trade, expressed as a human-readable decimal (e.g.,
"37.04" for USDC or "37.04" for USDT). Use this when you want the quote denominated in the pair token instead of cNGN. Provide this or cngnAmount, not both.boolean
default:"false"
When
true, the quote may be partially filled across multiple orderbook orders if no single order can fully satisfy the requested amount. When false (default), the quote is only generated if the full amount can be matched.Execute Trade
Execute an FX trade. Choose from three execution modes depending on how much price certainty and targeting you need.Before calling this endpoint, ensure the cNGN you intend to trade is held in your Fintech Smart Wallet. You can retrieve your smart wallet address from
GET /getfintechwallet.- Mode 1 - Quote (Recommended)
- Mode 2 - Direct
- Mode 3 - Targeted
- Response
Execute against a quote you obtained from
POST /fx/quote. This mode locks in the price shown in the quote and is the safest choice to avoid slippage.string
required
The
quoteId returned by POST /fx/quote. The quote must not be expired (valid for 15 minutes) or already used.string
An optional client-generated key to prevent duplicate trade submissions. If you retry a request with the same key and the original trade was accepted, the original trade is returned instead of creating a new one.
boolean
default:"false"
When
true, the trade may be partially filled across multiple orderbook orders if no single order can fully satisfy the requested amount. When false (default), the trade is only executed if the full amount can be matched.Create Market Order
Submit an immediate market order that executes at the current best available price from the orderbook. Market orders skip the quote step and settle based on your auto-signing configuration.Market orders execute against the best available limit orders at the time of submission, combining several orders if needed (see How orders are matched). If orderbook liquidity changes between your request and matching, the final fill price may differ slightly from what you observed in the orderbook stats. Use
POST /fx/quote followed by POST /fx/trade (Mode 1) if exact price certainty is required.- Request
- Response
string
required
Trading pair. Accepted values:
"CNGN-USDC" or "CNGN-USDT".string
required
Trade direction:
"sell" to exchange cNGN for the quote currency, or "buy" to acquire cNGN.string
required
Amount of cNGN to trade, in human-readable format (e.g.,
"50000" = 50,000 cNGN). Your wallet must hold at least this amount.string
On-chain address to receive the output tokens. Defaults to your registered fintech wallet if omitted.
string
Client-generated unique key to prevent duplicate order execution on retry.
boolean
default:"false"
When
true, the market order may be partially filled across multiple orderbook orders if no single order can fully satisfy the requested amount. When false (default), the order is only executed if the full amount can be matched.Get Trade Status
Retrieve the full details and current status of a single trade. Poll this endpoint to track a trade frompending through to completed or failed.
- Request
- Response
string
required
The
tradeId returned when the trade was created.List Trades
List your fintech’s FX trades with optional filters. Results are paginated using a cursor-based approach withstartAfter.
- Request
- Response
string
Filter by trading pair. Accepted values:
"CNGN-USDC" or "CNGN-USDT".string
Filter by trade direction. Accepted values:
"buy" or "sell". Case-insensitive.string
Filter by trade status. Case-insensitive. See the Trade Status Lifecycle section for all accepted values.
number
Maximum number of trades to return. Defaults to
50; maximum is 100.string
The
tradeId of the last trade in the previous page. Pass this value to fetch the next page of results.How orders are matched
Quote-based (Mode 1), direct (Mode 2), and market-order trades are matched against the orderbook in the same way:- Strails considers the 10 best-priced active orders on the opposite side of your trade: the lowest-priced
sellorders when you buy, and the highest-pricedbuyorders when you sell. - Your amount fills those orders in price order. If the best order cannot cover the full amount, the remainder spills into the next order, so one trade can fill across several liquidity providers. Each contributing order appears in the quote’s
matchedOrdersarray, andpriceis the volume-weighted average. - An order is skipped if the amount still to fill is below its
minAmount, if it has no remaining capacity, or if the liquidity provider’s wallet does not currently hold enough funds to honour it. - Quotes never include your own orders.
Insufficient liquidity
Orders are combined across liquidity providers whether or not you setallowPartialFill. The flag only decides what happens when all the matched orders together still cannot cover your amount:
allowPartialFill: false(default): the request is rejected withNO_LIQUIDITYand no trade is created.allowPartialFill: true: Strails fills what the matched orders can cover and leaves the rest unfilled. For a quote, this is decided when the quote is generated, so set the flag onPOST /fx/quote.
message explains why, for example that your amount is below the smallest available minAmount, that the matching liquidity providers’ wallets are underfunded, or that only part of the amount could be matched. Reduce your amount, split it into smaller trades, or retry when more liquidity is available.
Multi-order settlement
When a trade fills across more than one order, each order is settled as its own slice:- Buy trades need no MPC signature, so they move straight from
lockedtosettling. - Sell trades need each liquidity provider to sign the stablecoin transfer for their own slice, within the 15-minute price lock.
completed. If some slices of a sell trade settle and others fail or expire (for example, because one liquidity provider did not sign in time), the trade ends as partial: the settled slices are final, the cNGN for the unsettled slices is refunded from escrow, and the trade is flagged for review by Strails. If no slice settles, the trade is failed.
Trade Status Lifecycle
Every trade passes through the following statuses as it progresses from submission to final settlement:Status Flow
completed, partial, failed, and expired are final. When a trade expires or fails, the escrowed cNGN is automatically released back to your wallet.
Common Errors
FX error codes
When a quote or trade is rejected by the trading engine, the specific reason is returned indata.details.errorCode. Requests that fail schema validation return response_code 01 with the field errors in data.details.details and no errorCode.
Additional Notes
All cNGN and stablecoin amounts in request bodies use human-readable decimal notation (e.g.,
"50000" = 50,000 cNGN). All amounts in orderbook fields (price, minAmount, maxAmount, availableLiquidity) use the smallest unit with 6 decimal places. Divide those values by 1,000,000 to convert to human-readable form.Quotes and trade price locks both expire after exactly 15 minutes. Structure your integration to execute the trade immediately after generating a quote, and to poll
GET /fx/trade/status for settlement confirmation rather than relying on synchronous responses.