Execute Trade
Convert between stablecoins, Bitcoin, and NGN.
This endpoint allows you to perform a real-time asset conversion between supported assets. You can execute at current market rate or lock pricing using a previously generated quote ID.
Endpoint
Full request and response schema: Create Order in the API reference.
For the full request and response schema, see the Create Order API Reference.
Purpose
Use this endpoint to:
Execute a trade between supported currencies (USDT, USDC, Bitcoin, NGN) for a user or system wallet
Lock in pricing using a valid quote (quoteId)
Route funds directly to your Bitnob wallet for the destination asset
Track every trade via reference ID, Get Order By ID, and webhooks
Request Body Parameters
parameter | type | required | description |
|---|---|---|---|
base_currency | string | Yes | The base currency for the trade. One of: BTC, USDT, USDC, or NGN |
quote_currency | string | Yes | The quote currency for the trade. One of: BTC, USDT, USDC, or NGN. For naira trades, one side of the pair must be NGN |
side | string | Yes | The side of the trade. One of: buy or sell |
quantity | string | Yes | The amount of base currency to trade, in major units. Example: 0.0001 (BTC) or 5000 (₦5,000) |
price | string | Yes | The same price from the quote creation. Example: 88989.119625 |
quote_id | string | Conditional | The quote ID from the create quote response. Required for NGN pairs; optional for crypto pairs (omit to execute at the live market rate) |
reference | string | Recommended | Your idempotency key for this trade. On NGN pairs a repeat returns the original order. On crypto pairs a repeat is not rejected, so look the order up before retrying |
Example Request
Example Request (NGN pair)
For a naira trade, set base_currency to what you are spending and use side: "sell". quote_id is required — carry over the price and id from the quote.
Successful Response (201 Created)
Crypto pairs return 201 Created.
Response Fields
field | type | description |
|---|---|---|
id | string | Unique ID of the order |
base_currency | string | The base currency for the trade (e.g., USDT) |
quote_currency | string | The quote currency for the trade (e.g., BTC) |
side | string | The side of the trade (BUY or SELL) |
order_type | string | The type of order (e.g., limit) |
quantity | string | The quantity of base currency ordered |
price | string | The price at which the order was placed |
order.status | string | Status of the order (pending, filled, rejected, cancelled) |
created_at | string | ISO 8601 timestamp when order was created |
updated_at | string | ISO 8601 timestamp when order was last updated |
filled_quantity | string | The quantity that has been filled |
remaining_quantity | string | The quantity remaining to be filled |
quote_id | string | The quote ID used to lock the trade rate |
id | string | Unique ID of the fill |
order_id | string | The order ID this fill belongs to |
counterparty_order_id | string | The counterparty order ID matched against this fill |
quantity | string | The quantity filled |
created_at | string | ISO 8601 timestamp when fill was executed |
quote_id | string | The quote ID that was consumed by this trade |
consumed_quantity | string | The quantity consumed from the quote |
remaining_quantity | string | The quantity remaining on the quote |
is_exhausted | boolean | Whether the quote has been fully consumed |
Trade Behavior
If quote_id is provided:
The rate is locked
If the quote has expired, the order is rejected with 422 and "Quote <id> has expired". No funds move
If the quote does not exist, the order is rejected with 404
If quote_id is omitted (crypto pairs only):
The trade is executed at live market rate
Final output may vary slightly depending on real-time pricing
For NGN pairs: quote_id is always required — naira trades cannot execute at a live market rate, so the rate must be locked with a quote first. Each NGN quote backs one order.
Idempotency
Send a unique reference with every trade, and generate it before the first attempt. What a repeated reference does depends on the pair:
NGN pairs: the request returns the original order again, with the same id, and nothing is executed a second time. This holds even if you send a new quote_id.
Crypto pairs: the reference is not checked for uniqueness. A second request with the same reference can execute a second trade.
So after a timeout on a crypto order, do not resend blindly. Look it up first with GET /api/trading/orders/<your-reference> and resend only if it is not there. That lookup does not work for NGN orders (it returns 400 "invalid id"); for those, keep the order id from the response, or resend with the same reference to get the original order back.
Webhooks
On completion, Bitnob will emit:
event | when it fires |
|---|---|
trade.completed | When trade is successfully executed |
trade.failed | If the trade fails due to quote, balance, or system errors |
Errors
code | message | description |
|---|---|---|
400 | Invalid asset pair | Use a supported pair (USDT, USDC, BTC, NGN); naira trades need NGN on one side. |
400 | quote_id is required for NGN pairs — request a quote first | quote_id is mandatory for NGN pairs. |
400 | Validation failed | A required field is missing or malformed; details names each field. |
400 | Order too small: minimum 1.0 USDC | Crypto pairs have a minimum order size; the message names it. |
403 | NGN not enabled | Naira trading is not enabled on your account. Match on the status, not the text. |
404 | Quote <id> not found | The quote_id does not exist. |
422 | quote already consumed | NGN quotes back one order. Create a new quote. |
422 | Quote <id> has expired | The quote passed its expires_at. Create a new quote. Code is PRECONDITION_FAILED. |
422 | Insufficient balance | Source wallet doesn’t have enough funds. No funds move. |
500 | Execution failed | Internal issue; retry or contact support. |
503 | We couldn't process your order right now. No funds were charged. | The trading service is unavailable. Look the order up before retrying. |