Orders
Create and manage exchange orders. Status semantics and flow diagrams live in Order Lifecycle; authentication rules in Authentication.
Create Order
POST /orders/
Request
curl -X POST "https://api.n.exchange/en/api/v2/orders/" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "x-referral-token: YOUR_REFERRAL_TOKEN" \
-d '{
"deposit_amount": "500.00",
"deposit_currency": "USDTERC",
"withdraw_currency": "BTC",
"withdraw_address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"rate_id": "abc123-000000"
}'
Headers: Authorization required; x-referral-token recommended for attribution; X-User-Timezone optional — see Authentication.
Request fields:
| Field | Type | Required | Description |
|---|---|---|---|
deposit_currency | string or object | Yes | Currency you send. Three formats — see currency identification |
withdraw_currency | string or object | Yes | Currency you receive. Same three formats |
withdraw_address | string | Yes | Destination address. Must be non-blank and valid for the withdrawal currency's blockchain. Validation is format-level (regex/checksum per currency) — it cannot tell apart chains sharing a format (e.g. two EVM networks), so verify the address/chain pairing client-side |
deposit_amount | string | Conditional | Amount you send (max 8 decimals). Non-DeFi orders require deposit_amount or withdraw_amount; DeFi floating/fixed orders may omit both |
withdraw_amount | string | Conditional | Amount you receive (max 8 decimals). Same conditionality |
side | string | No | BUY (default) or SELL. Crypto swaps use BUY (just omit the field); SELL is for fiat flows. DeFi orders are always BUY. Treat side in responses as informational — don't use it to classify fiat vs crypto |
withdraw_address_extra_id | string | No | Memo/destination tag for the withdrawal (max 127 chars) |
refund_address | string | No* | Refund address — always denominated on the deposit currency's blockchain (refunds return where funds came from). Required for DeFi orders when the destination (withdraw) chain is non-EVM — currently Solana, Tron, Bitcoin |
refund_address_extra_id | string | No | Memo/destination tag for refund transactions (max 127 chars) |
rate_id | string | No | Quote id from the same GET /rate/ row. Binds order validation to that quote snapshot. Invalid/expired values fail validation |
is_defi | boolean | No | true = DeFi order (requires DeFi-enabled pair/currencies, min deposit $20 USD equivalent) |
is_fixed_rate | boolean | No | DeFi only: fixed-rate (RFQ) mode. Must not be combined with is_limit_order |
is_limit_order | boolean | No | DeFi only: limit order; requires limit_receive_amount |
limit_receive_amount | string | No | Limit-order minimum receive amount in human-readable destination units |
limit_ttl | integer | No | Limit-order TTL in seconds. Omitted/non-positive → backend default; positive values must meet the backend minimum |
markup | integer | No | Dynamic partner fee in basis points (0–10000). Pre-agreed capability; mutually exclusive with referral_rate (both → 400) |
referral_rate | string | No | Deprecated — use markup. Decimal fraction, e.g. "0.005" |
referral_code | string | No | CeFi referral code (≤20 chars, ^[A-Za-z0-9_-]+$). Must belong to the API key owner |
Example — object currency format with quote binding:
{
"deposit_amount": "500.00",
"deposit_currency": { "code": "USDT", "network": "ETH" },
"withdraw_currency": { "code": "BTC", "network": "BTC" },
"withdraw_address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"refund_address": "0xBCCbe8AF1d71D05F6eA1d9bE0E957cAd7b487b8F",
"rate_id": "waq1T39kPFn9LOETpzTnX6by7Yc-001ABB"
}
Response — 201 Created vs 200 Idempotent Reuse
| Status | Meaning |
|---|---|
201 | New order created |
200 | DeFi only: an existing matching order was returned instead of creating a duplicate |
For DeFi orders, a create request that matches one of your open orders — same pair, withdraw_address, mode flags (is_fixed_rate/is_limit_order), refund_address, and referral — returns 200 with the existing INITIAL order instead of minting a duplicate with a new deposit address. After a client-side timeout on a DeFi create, simply re-send the request. Treat 200 and 201 bodies identically.
CeFi order creation always returns 201 with a new order — a blind retry after a timeout can produce a duplicate with a different deposit address. Before retrying a CeFi create, check whether the first attempt succeeded (e.g. via GET /orders/ filtered by pair and status=INITIAL), or gate creation behind your own idempotency layer.
Response fields (OrderV2):
| Field | Type | Description |
|---|---|---|
unique_reference | string | Order identifier for tracking (^[A-Za-z0-9_-]+$) |
created_on | string | ISO 8601 creation timestamp |
side | string | BUY or SELL (read-only) |
status | string | Order status string — canonical values in Order Lifecycle |
deposit_currency / withdraw_currency | string | Always flat string codes in responses (e.g. "USDCARB"), regardless of the request format |
deposit_amount / withdraw_amount | string | Amounts (8 decimals); may be null on DeFi orders until execution |
deposit_address | string | Where you send funds |
deposit_address_extra_id | string | Memo/tag that must accompany the deposit, when required |
withdraw_address / withdraw_address_extra_id | string | Destination you provided |
refund_address / refund_address_extra_id | string | Refund destination you provided |
payment_window_minutes | integer | Deposit deadline window in minutes (see note below) |
fixed_rate_deadline | string/null | UTC timestamp until which the fixed rate holds |
rate | string | Exchange rate applied to the order |
deposit_transaction / withdraw_transaction | string | Transaction hashes, filled as they appear |
is_defi / is_fixed_rate / is_limit_order | boolean | Mode flags |
limit_expires_at | string/null | Limit-order expiry (limit orders) |
limit_min_received | string/null | Limit-order minimum, in destination smallest units as a string integer |
applied_referral_rate | string | Dynamic partner fee applied (only when a dynamic fee was requested) |
A null fixed_rate_deadline marks a floating-rate order: no rate deadline; the rate is determined when the deposit arrives. CeFi floating orders carry payment_window_minutes: 0 (a valid value, not an error); DeFi floating orders may carry a small nominal window — always key off fixed_rate_deadline. For fixed-rate orders, fixed_rate_deadline = created_on + payment_window_minutes. Countdown logic for UIs: Payment UI.
Example response (201):
{
"unique_reference": "ABCDEF123456",
"created_on": "2026-05-18T10:15:30Z",
"side": "BUY",
"status": "INITIAL",
"deposit_amount": "500.00000000",
"withdraw_amount": "0.01000000",
"deposit_currency": "USDTERC",
"withdraw_currency": "BTC",
"deposit_address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"deposit_address_extra_id": "",
"withdraw_address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"withdraw_address_extra_id": "",
"refund_address": "",
"refund_address_extra_id": "",
"payment_window_minutes": 60,
"fixed_rate_deadline": "2026-05-18T11:15:30Z",
"rate": "50000.00000000",
"deposit_transaction": "",
"withdraw_transaction": ""
}
DeFi orders
DeFi orders use the same endpoint with is_defi: true. The deposit_address returned is a proxy address; funds sent there are swapped non-custodially and delivered on the destination chain.
{
"deposit_currency": { "code": "SOL", "network": "SOL" },
"withdraw_currency": "BTC",
"withdraw_address": "bc1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"refund_address": "So1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"is_defi": true
}
side,deposit_amount,withdraw_amountare optional (treated asBUY; amount follows the actual deposit).- Minimum deposit: $20 USD equivalent; also respect the pair's
min_deposit_amountfromGET /rate/?is_defi=true. refund_addressis required when the destination (withdraw) chain is non-EVM — Solana, Tron, or Bitcoin. The address itself must be valid for the deposit currency's chain.- For fixed-rate DeFi, obtain an actionable quote first and pass its
rate_id.
{
"unique_reference": "AB12CD",
"created_on": "2026-02-20T10:00:00.000000Z",
"side": "BUY",
"is_defi": true,
"is_fixed_rate": false,
"status": "INITIAL",
"deposit_currency": "SOL",
"withdraw_currency": "BTC",
"deposit_amount": null,
"withdraw_amount": null,
"deposit_address": "0xProxyAddressFromDeFi",
"withdraw_address": "bc1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"refund_address": "So1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"deposit_transaction": "",
"withdraw_transaction": "",
"rate": "0.0",
"payment_window_minutes": 1,
"fixed_rate_deadline": null
}
is_defiGET /orders/{unique_reference}/ for a DeFi order may not include the is_defi flag itself. If your UI branches on order mode, persist the mode at creation time instead of inferring it from the detail response. See Payment UI patterns.
DeFi limit orders
Limit orders target a minimum receive amount instead of a quoted rate. is_limit_order must not be combined with is_fixed_rate, and rate_id does not apply.
{
"deposit_currency": { "code": "ETH", "network": "ETH" },
"withdraw_currency": { "code": "USDT", "network": "ETH" },
"withdraw_address": "0xBCCbe8AF1d71D05F6eA1d9bE0E957cAd7b487b8F",
"refund_address": "0xBCCbe8AF1d71D05F6eA1d9bE0E957cAd7b487b8F",
"is_defi": true,
"is_limit_order": true,
"limit_receive_amount": "20",
"limit_ttl": 3600
}
limit_receive_amount— human-readable destination units; converted internally to smallest units (read back aslimit_min_received, a string integer in smallest units).limit_ttl— seconds. Omitted or non-positive → the default TTL (currently 24 hours). Positive values must be at least 600 seconds; smaller values return400(limit_ttl must be at least 600 seconds (10 minutes).).- Read back
limit_expires_atfor the effective expiry.
List Orders
GET /orders/
Returns CeFi orders only with cursor pagination. DeFi orders do not appear in the list — track them individually via Get Order.
Request
curl -X GET "https://api.n.exchange/en/api/v2/orders/?page_size=25" \
-H "Accept: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY"
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
cursor | string | No | Opaque cursor from pagination.next / pagination.previous |
page_size | integer | No | 1–100, default 25 |
pair | string | No | Pair name filter, e.g. BTCETH |
status | integer or string | No | Status filter — accepts the numeric code (?status=11) or the exact status name (?status=INITIAL). Mapping: Order Lifecycle. Unknown values return an empty list |
The list uses cursor pagination — there is no page parameter and no total count. Follow pagination.next until has_next is false. Ordering is -created_on, -id (newest first).
Response
{
"pagination": {
"next": "https://api.n.exchange/en/api/v2/orders/?cursor=cD0yMDI2LTA1LTE3VDE0JTNBMDAlM0EwMFo%3D",
"previous": null,
"has_next": true,
"has_previous": false,
"page_size": 25,
"ordering": ["-created_on", "-id"]
},
"results": [
{
"unique_reference": "ABCDEF123456",
"created_on": "2026-05-18T10:15:30Z",
"side": "BUY",
"withdraw_amount": "0.01000000",
"deposit_amount": "500.00000000",
"deposit_currency": "USDTERC",
"withdraw_currency": "BTC",
"withdraw_address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"withdraw_address_extra_id": "",
"deposit_address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"deposit_address_extra_id": "",
"refund_address": "",
"refund_address_extra_id": "",
"payment_window_minutes": 60,
"fixed_rate_deadline": "2026-05-18T11:15:30Z",
"status": "COMPLETED",
"rate": "50000.00000000",
"deposit_transaction": "8a3f4c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f",
"withdraw_transaction": "0xfeed1234feed1234feed1234feed1234feed1234feed1234feed1234feed1234"
}
]
}
Get Order
GET /orders/{unique_reference}/
Works for both CeFi and DeFi orders. Returns every OrderV2 field plus:
| Field | Type | Description |
|---|---|---|
amount_usd | number/null | USD equivalent value. CeFi orders only; null/absent for DeFi |
curl -X GET "https://api.n.exchange/en/api/v2/orders/ABCDEF123456/" \
-H "Accept: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY"
Poll this endpoint to track progress — recommended cadence and stop conditions in Order Tracking.
Update Order
PATCH /orders/{unique_reference}/
All fields optional; send only what you are changing.
| Field | Type | Description |
|---|---|---|
withdraw_address | string | Set the withdrawal address — only once, and only before processing starts |
withdraw_address_extra_id | string | Memo/tag for the withdrawal (max 127 chars) |
marked_as_paid | boolean | true = mark the order paid (optionally with deposit_transaction for faster crediting); false = cancel the pending payment |
deposit_transaction | string | Self-served deposit transaction hash |
referral_code | string | Referral code (≤20 chars; must belong to the API key owner) |
curl -X PATCH "https://api.n.exchange/en/api/v2/orders/ABCDEF123456/" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey YOUR_API_KEY" \
-d '{
"marked_as_paid": true,
"deposit_transaction": "8a3f4c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f"
}'
Returns 200 with the updated OrderV2.
The PATCH parameter is marked_as_paid. The related read-only flag exposed on some order payloads is user_marked_as_paid — the value you set is reflected there. Marking as paid is optional: deposits are detected automatically by chain monitoring; use it (with the tx hash) to speed crediting up, or marked_as_paid: false to cancel an unpaid order.
Re-submitting a deposit_transaction that is already recorded returns a 400 with an "already exists" style validation message — safe to treat as success in retry logic. See Errors & Rate Limits.
Errors
| Status | When | Body shape |
|---|---|---|
400 | Validation failure — missing fields, invalid/expired rate_id, amount outside limits, markup+referral_rate together, invalid address | {"detail": "...", "errors": {"field": ["..."]}} |
401 | Missing/invalid API key, or referral code not owned by the key owner | {"detail": "..."} |
404 | Unknown unique_reference | {"detail": "Not found"} |
Retryability of specific validation errors (expired quotes, transient DeFi quote failures) is catalogued in Errors & Rate Limits.
Next steps
- Order Lifecycle — statuses, flows, refunds
- Order Tracking — polling guidance
- Webhooks — push notifications