POST /v1/create
Create an order, reserve a pay-in address, receive the one-time access token.
/api/v1/createAuth requiredCreates an order and reserves a pay-in address. Amount and rate math is recomputed server-side from the same engine as /v1/price. Your amount is a quote hint, never the wire value. The server applies your afftax, enforces USD min/max caps, and records earnings against this order for reconciliation.
data.token is returned once. Cleartext is never persisted server-side. Store it on receipt. Losing it means the order is unreachable from the API (still visible in the cabinet).
Request
type"float"requiredfromCcystringrequiredtoCcystringrequiredfromNetworkstringtoNetworkstringdirection"from" | "to"requiredamountstring | numberrequiredtoAddressstring (10..200 chars)requiredtagstring | nullrefundAddressstringrequiredafftaxintegerResponse
{
"code": 0,
"msg": "",
"data": {
"id": "1f8c5e0b-9c92-4d6a-b0a8-3c5f8d6e7a4b",
"type": "float",
"status": "NEW",
"time": {
"reg": 1716800000,
"expiration": 1716801800,
"left": 1800,
"update": 1716800000,
"finish": null
},
"from": {
"code": "btc",
"network": "Bitcoin",
"amount": "0.01000000",
"address": "bc1q...generated-payin-address",
"tx": { "id": null, "amount": null }
},
"to": {
"code": "usdt_trc20",
"network": "Tron",
"amount": "619.987654",
"address": "TXyz...your-recipient-address",
"tx": { "id": null, "amount": null }
},
"back": {
"address": "bc1q...your-refund-address",
"tx": { "id": null }
},
"emergency": { "status": [], "choice": "NONE" },
"rate": "62450.12345678",
"networkFee": "1.20",
"markupBps": 50,
"token": "v8k3-Po9...43-char-base64url-token"
}
}data.idstring (UUID)data.tokenstring (43-char base64url) | nullIdempotency-Key. The cleartext value is never persisted on our side. Store it on receipt. Idempotent replays of the same key return the same order with data.token: null: the token is only shown on the first call. If you lose it, re-issue the order with a fresh Idempotency-Key.data.status"NEW" | "PENDING" | ...NEW.data.time.{reg,expiration,left,update,finish}number (unix seconds)reg is creation time, expiration is the deposit deadline, left is seconds remaining, update is the last row mutation, and finish is the payout-sent timestamp (null until DONE).data.from / data.toobjectdata.from.tx / data.to.tx{ id: string|null, amount: string|null }data.back.addressstringdata.back.tx.idstring | nulldata.emergency.{status,choice}array, stringNONE on a freshly-created order. See Status mapping for the values populated when the order enters EMERGENCY.data.rate / data.networkFee / data.markupBpsstring, string, number|nullErrors
| code | msg | HTTP | Description |
|---|---|---|---|
| 1 | INVALID_REQUEST | 400 | Body fails validation: unsupported asset, disabled pair, unparseable amount, invalid address, FLOAT without refundAddress, malformed Idempotency-Key. The same code + HTTP 409 fires on Idempotency-Key reuse with a different payload. |
| 2 | AUTH_REQUIRED | 401 | One of X-API-KEY / X-API-SIGN is missing on an endpoint that requires authentication. |
| 3 | AUTH_INVALID | 401 | Unknown key, malformed signature, signature mismatch, expired or replayed nonce, decrypt failure. Generic body — never an oracle for "which" of those it was. |
| 4 | AUTH_DISABLED | 401 | Partner record enabled = false. Reachable only with a valid signature, so the operator can distinguish a kill-switched partner from a stolen-and-revoked key. |
| 5 | RATE_LIMIT | 429 | Per-partner weight budget exhausted within the 60-second sliding window. Response includes Retry-After: <seconds>. |
| 6 | NOT_FOUND | 404 | Order does not exist OR exists but belongs to a different partner OR exists and the token is wrong. The three cases collapse to one envelope. |
| 7 | LIMIT_MIN | 400 | Create amount below the per-pair USD minimum. /v1/price returns from.min / to.min for pre-validation but does not itself emit this code. |
| 8 | LIMIT_MAX | 400 | Create amount above the per-pair USD maximum or the operator daily cap. /v1/price returns from.max / to.max for pre-validation but does not itself emit this code. |
| 10 | MAINTENANCE | 503 | The site is in operator-toggled upgrade mode. Retry after a short delay. |
| 11 | UPSTREAM_ERROR | 503 | A required upstream is temporarily unavailable. Retry with exponential backoff. |
| 99 | INTERNAL | 500 | Unexpected server-side condition. Already logged on our side; safe to retry. |
Code examples
# Create an order. Auth is required. The 'Idempotency-Key' header
# makes retries safe — same key + same body returns the same order id
# without creating duplicates.
APIKEY="rWqZ...Rg"
APISECRET="G1JV...n4"
NONCE=$(openssl rand -hex 16)
IDEMP=$(openssl rand -hex 12)
BODY='{"type":"float","fromCcy":"btc","toCcy":"usdt_trc20","direction":"from","amount":"0.01","toAddress":"TXyz...your-recipient-address","refundAddress":"bc1q...your-refund-address","afftax":50}'
SIGN=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$APISECRET" | sed 's/^.* //')
curl -sS -X POST "https://0trace.io/api/v1/create" \
-H "Content-Type: application/json" \
-H "X-API-KEY: $APIKEY" \
-H "X-API-SIGN: $SIGN" \
-H "X-API-NONCE: $NONCE" \
-H "Idempotency-Key: $IDEMP" \
--data "$BODY"
# Save data.id and data.token from the response — the token is shown
# exactly once and cannot be recovered.Rate limit
Weight 50 per call. 50 weight units per call (≈ 50 creates per minute at the default 2500 wu/min budget).
Notes
Idempotency. Send an Idempotency-Key header (8..128 chars) so retries are safe. A replay with the same body returns the existing order. A replay with a different body returns code 1 INVALID_REQUEST with HTTP 409. Idempotent replays return no token: you already received it on the first call.
Server-computed pricing. The create path re-runs the same pricing logic as /v1/price, so it cannot be tricked into accepting a stale quote. If the rate moved between your quote and create, the order amount reflects the new rate, not the quote you saw.
Site upgrade mode. When the site is flagged for maintenance, the response is { code: 10, msg: "MAINTENANCE" } with HTTP 503. Retry after a short delay.