https://nonlogs.io
Build with Nonlogs
Read live markets and order books publicly, or use a signed API key to place and manage limit orders.
External swaps require explicit permission. API keys cannot change security settings or access administrator functions; this deployment does not expose account withdrawals.
Overview
application/json
HMAC-SHA256
5/sec · 300/min
External-wallet swaps
Create a customer swap using an API key with External swaps permission. Use the signed-request headers and signature format documented below for every endpoint. No CAPTCHA or browser session is required. Keep API secrets on your server, never in customer-side JavaScript.
The customer sends funds to the returned deposit address. This does not spend your NonLogs balance. Prices float until execution; estimates are not guaranteed. Normal trading fees, a 0.8% convenience fee and outgoing network charges apply. Your API account receives 50% of collected customer trading fees and 50% of the convenience fee, in the same coins, automatically. No referral link is needed; unfunded swaps and untraded refunds earn nothing. Provable self-referrals are excluded.
/api/v1/swaps/assetsReturns creation_enabled and assets with symbols, exact networks, availability and confirmation requirements. A traded coin is not necessarily eligible for external swaps. Check availability before funding.
/api/v1/swaps/quote{"from":"BTC","to":"XMR","amount":"0.001","from_network":"bitcoin","to_network":"monero"}Returns estimated receipt, itemized fees, minimum/suggested/maximum amounts, route and queued-execution terms. This allocates no address and reserves neither a price nor liquidity. Network fields may be omitted only if the symbol has exactly one catalogued network.
/api/v1/swaps{"from":"BTC","to":"XMR","amount":"0.001","from_network":"bitcoin","to_network":"monero","payout_address":"CUSTOMER_MONERO_ADDRESS","refund_address":"CUSTOMER_BITCOIN_ADDRESS","client_request_id":"8b6d7b3b-342f-4c1f-86f7-b29ef302266a"}Both addresses are required and cannot be changed after creation. Returns id, client_request_id, deposit_address, address_tag (nullable), deposit_payment_uri, swap_url, funding_status, funding_expires_at, the estimate fields and payments. The private URL uses https://nonlogs.io/swap/status#14_CHARACTER_CODE; the code remains in the fragment. Treat the whole URL as a secret and never log it or place it in analytics.
First creation returns 201; an identical retry returns 200 with the same address, terms and link. Reusing a request ID with different inputs returns 409. After a timeout or 503, retry the same request ID with a fresh signature timestamp and nonce—never allocate another ID to recover an uncertain result.
/api/v1/swaps/{id}Returns the same swap projection with current per-payment confirmations, conversion progress, fee amounts, payouts and refunds. Outgoing transfers include kind, status, amount (nullable before preparation), network_fee and tx_hash. Poll about every 10 seconds while needed. No webhooks or customer cancellation endpoint are provided.
Funding-window state is separate from payment state: an expired window does not mean an earlier deposit or payout failed. Any active swap-enabled key on your account can read and recover your API swaps after key rotation. It cannot read another account's swaps or unrelated browser swaps.
Amounts are decimal strings, not JSON numbers or exponent notation. Fees are denominated in the displayed asset; trade-fee entries each carry their own symbol. API timestamps are UTC ISO 8601. Funding is open for 24 hours. Deposits are processed individually using their actual amounts; confirmed and spendable payments may wait up to 12 hours for matching. Partial execution can produce both a destination payout and a source refund. Existing approval and network safety rules still apply.
Limits are account-wide across keys: initially 10 new sessions per minute and 50 unexpired funding sessions, plus shared address-pool/backlog caps and normal API request limits. Retries do not allocate another slot. A 429 includes Retry-After; 401 indicates authentication failure, 403 missing permission, 404 inaccessible swap, 422 invalid inputs or unavailable route, and 503 a pause or temporarily uncertain outcome. Pausing new creation does not stop status access, monitoring or existing obligations.
When creating a key through the credential interface, set external_swaps: true and provide the current password and a fresh authenticator code if enabled. Existing keys do not gain this permission automatically. All keys retain their existing trading permissions; enable ordinary withdrawal access only if you separately need it.
Public market data
/api/marketsReturns prices, 24-hour volume, high/low, best bid, and best ask for every active market.
{"markets":{"BTC-USDT":{"last_price":"68124.12000000","high_24h":"69400.00000000","low_24h":"67250.00000000","base_volume":"12.34000000","quote_volume":"840000.000000","lowest_ask":"68130.00000000","highest_bid":"68120.00000000","percent_change":1.24}}}
/api/markets/{pair}Returns the same ticker fields for one pair, such as BTC-USDT.
/pair/pairs?skip=0&limit=100Lists active pairs and their base/quote asset metadata. The maximum limit is 100.
/pair/pairs/{pair}Returns metadata and supported decimal precision for one active pair.
/order/orderbook/{pair}?depth=20Returns aggregated bids and asks as [price, quantity] string tuples. Depth may be 1–100.
{"pair":"BTC-USDT","timestamp":"2026-08-08T08:00:00Z","bids":[["68120.00000000","0.25000000"]],"asks":[["68130.00000000","0.10000000"]]}
Authentication
Send all four headers below. Timestamps must be within 30 seconds of server time and every hexadecimal nonce may be used only once.
| Header | Value |
|---|---|
X-API-Key | Your public API key |
X-Timestamp | Unix timestamp in seconds |
X-Nonce | Unique hexadecimal string, 16–128 characters |
X-Signature | Lowercase HMAC-SHA256 hexadecimal digest |
Canonical payload
METHOD
PATH
TIMESTAMP
NONCE
SORTED_QUERY
BODY
Use the uppercase method, path beginning with /, query
parameters sorted by key and RFC 3986 encoded, and the exact raw
JSON body. Use an empty line when query or body is absent. The
signature is hex(HMAC_SHA256(api_secret, payload)).
Python signing example
import hashlib, hmac, json, secrets, time
from urllib.parse import urlencode
method = "POST"
path = "/tradeuser/orders/limit"
query = {}
body = json.dumps({
"pair": "BTC-USDT",
"type": "LIMIT",
"operation": "BUY",
"quantity": "0.00100000",
"price": "68000.00000000"
}, separators=(",", ":"))
timestamp = str(int(time.time()))
nonce = secrets.token_hex(16)
sorted_query = urlencode(sorted(query.items()), safe="~")
payload = "\n".join([method, path, timestamp, nonce, sorted_query, body])
signature = hmac.new(API_SECRET.encode(), payload.encode(), hashlib.sha256).hexdigest()
Limit orders
Price and quantity must be JSON strings. Numeric JSON values are rejected so clients cannot silently round financial values.
/tradeuser/orders/limitPlaces a good-till-cancelled limit order and locks the required balance atomically.
{"pair":"BTC-USDT","type":"LIMIT","operation":"BUY","quantity":"0.00100000","price":"68000.00000000","client_order_id":"00000000-0000-4000-8000-000000000001"}
client_order_id is required. Generate and persist a new UUID before the first request, then reuse that UUID for every retry of the same order.
/tradeuser/orders?pair=BTC-USDT&state=OPEN&skip=0&limit=50Lists the key owner's orders. State may be OPEN, FILLED, or CANCELLED; maximum limit is 50.
/tradeuser/orders/{id}Cancels an owned open order, releases its remaining balance hold, and returns 204 No Content.
Errors and retries
Errors use a stable machine-readable code:
{"error":{"code":"invalid_signature","message":"The request signature is invalid."}}
Respect 429 and its Retry-After header.
Retry read requests after temporary 503 responses. For
order placement, use a persistent client_order_id UUID
before retrying an uncertain client connection.