Skip to main content
Version: v2

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:

FieldTypeRequiredDescription
deposit_currencystring or objectYesCurrency you send. Three formats — see currency identification
withdraw_currencystring or objectYesCurrency you receive. Same three formats
withdraw_addressstringYesDestination 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_amountstringConditionalAmount you send (max 8 decimals). Non-DeFi orders require deposit_amount or withdraw_amount; DeFi floating/fixed orders may omit both
withdraw_amountstringConditionalAmount you receive (max 8 decimals). Same conditionality
sidestringNoBUY (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_idstringNoMemo/destination tag for the withdrawal (max 127 chars)
refund_addressstringNo*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_idstringNoMemo/destination tag for refund transactions (max 127 chars)
rate_idstringNoQuote id from the same GET /rate/ row. Binds order validation to that quote snapshot. Invalid/expired values fail validation
is_defibooleanNotrue = DeFi order (requires DeFi-enabled pair/currencies, min deposit $20 USD equivalent)
is_fixed_ratebooleanNoDeFi only: fixed-rate (RFQ) mode. Must not be combined with is_limit_order
is_limit_orderbooleanNoDeFi only: limit order; requires limit_receive_amount
limit_receive_amountstringNoLimit-order minimum receive amount in human-readable destination units
limit_ttlintegerNoLimit-order TTL in seconds. Omitted/non-positive → backend default; positive values must meet the backend minimum
markupintegerNoDynamic partner fee in basis points (0–10000). Pre-agreed capability; mutually exclusive with referral_rate (both → 400)
referral_ratestringNoDeprecated — use markup. Decimal fraction, e.g. "0.005"
referral_codestringNoCeFi 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

StatusMeaning
201New order created
200DeFi only: an existing matching order was returned instead of creating a duplicate
DeFi idempotency

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 creates are NOT idempotent

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):

FieldTypeDescription
unique_referencestringOrder identifier for tracking (^[A-Za-z0-9_-]+$)
created_onstringISO 8601 creation timestamp
sidestringBUY or SELL (read-only)
statusstringOrder status string — canonical values in Order Lifecycle
deposit_currency / withdraw_currencystringAlways flat string codes in responses (e.g. "USDCARB"), regardless of the request format
deposit_amount / withdraw_amountstringAmounts (8 decimals); may be null on DeFi orders until execution
deposit_addressstringWhere you send funds
deposit_address_extra_idstringMemo/tag that must accompany the deposit, when required
withdraw_address / withdraw_address_extra_idstringDestination you provided
refund_address / refund_address_extra_idstringRefund destination you provided
payment_window_minutesintegerDeposit deadline window in minutes (see note below)
fixed_rate_deadlinestring/nullUTC timestamp until which the fixed rate holds
ratestringExchange rate applied to the order
deposit_transaction / withdraw_transactionstringTransaction hashes, filled as they appear
is_defi / is_fixed_rate / is_limit_orderbooleanMode flags
limit_expires_atstring/nullLimit-order expiry (limit orders)
limit_min_receivedstring/nullLimit-order minimum, in destination smallest units as a string integer
applied_referral_ratestringDynamic partner fee applied (only when a dynamic fee was requested)
Floating orders have no deadline

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.

DeFi floating-rate request
{
"deposit_currency": { "code": "SOL", "network": "SOL" },
"withdraw_currency": "BTC",
"withdraw_address": "bc1qxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"refund_address": "So1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"is_defi": true
}
  • side, deposit_amount, withdraw_amount are optional (treated as BUY; amount follows the actual deposit).
  • Minimum deposit: $20 USD equivalent; also respect the pair's min_deposit_amount from GET /rate/?is_defi=true.
  • refund_address is 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.
DeFi response (note: amounts null until execution)
{
"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
}
DeFi detail responses omit is_defi

GET /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.

Limit order request
{
"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 as limit_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 return 400 (limit_ttl must be at least 600 seconds (10 minutes).).
  • Read back limit_expires_at for 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:

ParameterTypeRequiredDescription
cursorstringNoOpaque cursor from pagination.next / pagination.previous
page_sizeintegerNo1–100, default 25
pairstringNoPair name filter, e.g. BTCETH
statusinteger or stringNoStatus filter — accepts the numeric code (?status=11) or the exact status name (?status=INITIAL). Mapping: Order Lifecycle. Unknown values return an empty list
Cursor, not page numbers

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:

FieldTypeDescription
amount_usdnumber/nullUSD 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.

FieldTypeDescription
withdraw_addressstringSet the withdrawal address — only once, and only before processing starts
withdraw_address_extra_idstringMemo/tag for the withdrawal (max 127 chars)
marked_as_paidbooleantrue = mark the order paid (optionally with deposit_transaction for faster crediting); false = cancel the pending payment
deposit_transactionstringSelf-served deposit transaction hash
referral_codestringReferral 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.

Field name

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

StatusWhenBody shape
400Validation failure — missing fields, invalid/expired rate_id, amount outside limits, markup+referral_rate together, invalid address{"detail": "...", "errors": {"field": ["..."]}}
401Missing/invalid API key, or referral code not owned by the key owner{"detail": "..."}
404Unknown unique_reference{"detail": "Not found"}

Retryability of specific validation errors (expired quotes, transient DeFi quote failures) is catalogued in Errors & Rate Limits.

Next steps