API Documentation

0xSwap Partner API

Backend integration reference for currencies, live quotes, automatic order creation, status lookup, client IP forwarding, aliases, and legacy route compatibility.

Base URL

https://zeroxswap.com

HTTPS only

JSON request bodies

Backend-only credentials

Overview

How integrations should work

01

Call from your backend

Partner credentials must never be exposed in browser code.

02

Pass clientIp

Send the real end-user IP when your server proxies order creation.

03

Store order data

Persist orderNumber, token, client_reference, and your idempotency key immediately after create-order succeeds.

Quick start

curl -X POST https://zeroxswap.com/api/partner/price \
  -H "Content-Type: application/json" \
  -H "X-API-Public-Key: $OXSWAP_PUBLIC_KEY" \
  -H "X-API-Secret-Key: $OXSWAP_SECRET_KEY" \
  -d '{
    "fromCcy": "BTC",
    "toCcy": "USDTTRC",
    "direction": "from",
    "amount": 0.015
  }'

Runtime contract

Order lifecycle and polling

01

Create the order

Call create-order from your backend and return the deposit address to the user.

02

Persist identifiers

Store orderNumber, token, client_reference, local idempotency key, local order id, and initial status before showing success.

03

Poll until terminal

Check order status after creation and continue polling while it is NEW, PENDING, EXCHANGE, or WITHDRAW.

04

Fulfill only DONE

Trigger idempotent fulfillment only for the exact DONE status. Route every unknown status to manual review.

Required polling pattern

const activeStatuses = new Set([
  "NEW",
  "PENDING",
  "EXCHANGE",
  "WITHDRAW"
]);

async function poll0xSwapOrder(orderNumber) {
  let delayMs = 10000;

  while (true) {
    const response = await fetch(
      `https://zeroxswap.com/api/partner/order/${orderNumber}`,
      { headers: partnerAuthHeaders }
    );
    const payload = await response.json();
    const status = payload.data?.status;

    await saveStatus(orderNumber, status, payload.data);

    if (status === "DONE") {
      await fulfillOnce(orderNumber, payload.data);
      return payload.data;
    }

    if (status === "EXPIRED" || status === "REFUND") {
      return payload.data;
    }

    if (!activeStatuses.has(status)) {
      await queueForManualReview(orderNumber, status, payload.data);
      return payload.data;
    }

    await sleep(delayMs);
    delayMs = 30000;
  }
}

Do not stop at NEW

The create response is only the initial state. A single immediate status check can still return NEW because the user has not paid yet or the provider has not finished.

Keep polling

NEW, PENDING, EXCHANGE, WITHDRAW

Fulfill exactly once

DONE only

Stop without fulfillment

EXPIRED, REFUND

Manual review

COMPLETE, COMPLETED, or any unknown status

Preflight

Integration checklist

01

Credentials are used only from server-side code.

02

Real end-user IP is sent as clientIp for server-to-server creates.

03

Every create uses a unique X-Idempotency-Key; a lost response is retried with the exact same key and body.

04

orderNumber, token, client_reference, and the local idempotency key are stored before success is shown.

05

Status polling continues until a terminal status, not just once after create.

06

DONE fulfillment is idempotent and safe to retry.

07

EXPIRED, REFUND, COMPLETE, COMPLETED, and unknown statuses never trigger automatic fulfillment.

08

Network and 5xx errors retry without marking the local order failed.

09

Partner secrets, API keys, and raw signatures are never written to logs.

10

Support requests include orderNumber and local order id when available.

Security

Authentication

Route familyPartner
HeadersX-API-Public-Key, X-API-Secret-Key
NotesRecommended for new integrations. Keep both headers on your backend only.
Route familyLegacy v1
HeadersX-API-KEY, X-API-SIGN
NotesSignature is HMAC-SHA256 over the raw JSON body.

Partner order ownership

An authenticated Partner API key can read only orders created under that same key. The provider performs this ownership check before any upstream status synchronization. A foreign order number and an unknown order number are deliberately indistinguishable and return the same response.

Foreign or missing order

HTTP/1.1 404 Not Found

{
  "code": 3,
  "error": "Order not found"
}

Context

Client IP and timezone forwarding

For server-to-server create requests, include clientIp. Without it, the order will show the IP of your backend server.

Fallback extraction order is cf-connecting-ip, x-real-ip, then the first x-forwarded-for value.

Optional client time fields are clientLocalTime, clientTimezone, and clientUtcOffset.

GET/api/partner/ccies

Currencies

Returns enabled currencies in the same priority order used by the public exchange selector.

Request fields

Fieldnone
Type-
Required-
DescriptionNo request body.

Response fields

Fieldcode
Typestring
DescriptionCurrency code accepted by the API.
Fieldcoin
Typestring
DescriptionBase asset symbol.
Fieldnetwork
Typestring
DescriptionNetwork name, for example BTC, ETH, TRC20.
Fieldrecv / send
Typeboolean
DescriptionWhether the asset can be deposited or paid out.
Fieldtag
Typestring | null
DescriptionRequired memo/tag field name when the network needs one.
Fieldpriority
Typenumber
DescriptionSorting priority used by the public selector.
POST/api/partner/price

Live quote

Returns pair limits and an estimated route amount for direction = from or direction = to.

Request fields

FieldfromCcy
Typestring
Requiredyes
DescriptionAsset the user sends. Alias-compatible.
FieldtoCcy
Typestring
Requiredyes
DescriptionAsset the user receives. Alias-compatible.
Fielddirection
Type"from" | "to"
Requiredyes
DescriptionUse from for send amount, to for receive target.
Fieldamount
Typenumber
Requiredyes
DescriptionPositive amount in the selected direction.

Response fields

Fieldfrom / to
Typeobject
DescriptionResolved amounts, coin, network, limits, and rate.
Fielderrors
Typearray
DescriptionProvider or validation hints. Empty on success.
Fieldmode
Typestring
DescriptionCurrent route mode.

Request example

{
  "fromCcy": "BTC",
  "toCcy": "ETH",
  "direction": "from",
  "amount": 0.01
}

Response example

{
  "code": 0,
  "data": {
    "from": {
      "code": "BTC",
      "coin": "BTC",
      "network": "BTC",
      "amount": "0.01",
      "min": "0.0000127",
      "max": "1000000",
      "rate": 35.84
    },
    "to": {
      "code": "ETH",
      "coin": "ETH",
      "network": "ETH",
      "amount": "0.3584",
      "min": "0.0022",
      "max": "1000000",
      "rate": 35.84
    },
    "errors": [],
    "mode": "auto"
  }
}
POST/api/partner/create-order

Create order

Creates an automatic provider-backed order and returns a deposit address plus tracking token.

Request fields

FieldfromCcy
Typestring
Requiredyes
DescriptionAsset the user sends. Alias-compatible.
FieldtoCcy
Typestring
Requiredyes
DescriptionAsset the user receives. Alias-compatible.
Fielddirection
Type"from" | "to"
Requiredyes
DescriptionDirection used for amount.
Fieldamount
Typenumber
Requiredyes
DescriptionPositive amount.
FieldtoAddress
Typestring
Requiredyes
DescriptionDestination payout address.
FieldtoTag
Typestring | null
Requiredconditional
DescriptionRequired when the selected payout currency has a tag field.
Fieldemail
Typestring | null
Requiredoptional
DescriptionEnd-user email for order context when available.
FieldclientIp
Typestring
Requiredrecommended
DescriptionReal end-user IP for server-to-server integrations.
FieldclientLocalTime
Typestring
Requiredoptional
DescriptionClient local timestamp for support context.
FieldclientTimezone
Typestring
Requiredoptional
DescriptionIANA timezone, for example Europe/Berlin.
FieldclientUtcOffset
Typestring
Requiredoptional
DescriptionUTC offset, for example UTC +02:00.
FieldX-Idempotency-Key
Typeheader string
Requiredstrongly required
DescriptionRequired for Bulk PSN. Case-sensitive, 8-200 printable non-space ASCII characters; never reuse for another order.

Response fields

FieldorderNumber
Typestring
DescriptionPublic order id. Automatic orders use C-prefixed ids.
Fieldtoken
Typestring
DescriptionSecret tracking token. Store it server-side.
Fieldclient_reference
Typestring
DescriptionStable provider reference returned for a reserved idempotent request and repeated by order status.
Fieldfrom.address
Typestring
DescriptionDeposit address for the user.
FieldtimeLeft
Typenumber
DescriptionRemaining deposit window in seconds.

Request example

curl -X POST https://zeroxswap.com/api/partner/create-order \
  -H "Content-Type: application/json" \
  -H "X-API-Public-Key: $OXSWAP_PUBLIC_KEY" \
  -H "X-API-Secret-Key: $OXSWAP_SECRET_KEY" \
  -H "X-Idempotency-Key: bulk-order-2026-0001" \
  -d '{
  "fromCcy": "BTC",
  "toCcy": "USDTTRC",
  "direction": "from",
  "amount": 0.015,
  "toAddress": "TRON_DESTINATION_ADDRESS",
  "toTag": null,
  "email": "buyer@example.com",
  "clientIp": "203.0.113.14",
  "clientLocalTime": "2026-05-20 00:33:25",
  "clientTimezone": "Europe/Berlin",
  "clientUtcOffset": "UTC +02:00"
}'

Response example

{
  "code": 0,
  "data": {
    "orderNumber": "C4M2Q9",
    "token": "secure-order-token",
    "status": "NEW",
    "client_reference": "idem_11111111111111111111111111111111",
    "from": {
      "code": "BTC",
      "amount": "0.015",
      "address": "bc1q...",
      "tag": null,
      "txId": null
    },
    "to": {
      "code": "USDTTRC",
      "amount": "1543.42",
      "address": "TRON_DESTINATION_ADDRESS",
      "tag": null,
      "txId": null
    },
    "timeLeft": 1200,
    "timeExpiration": 1770000000
  }
}
GET/api/partner/order/:orderNumber

Order status

Returns the latest status only for an order owned by the authenticated API key. Foreign and unknown order numbers return the same 404 response.

Request fields

FieldorderNumber
Typepath string
Requiredyes
DescriptionPublic order number returned by create-order.

Response fields

Fieldstatus
Typestring
DescriptionCurrent order status.
Fieldclient_reference
Typestring | omitted
DescriptionStable reference for orders created with X-Idempotency-Key; omitted for legacy orders.
Fieldfrom.txId
Typestring | null
DescriptionDeposit transaction hash when known.
Fieldto.txId
Typestring | null
DescriptionPayout transaction hash when known.
FieldtimeExpiration
Typenumber
DescriptionUnix timestamp for order expiration.

Response example

{
  "code": 0,
  "data": {
    "orderNumber": "C4M2Q9",
    "status": "EXCHANGE",
    "client_reference": "idem_11111111111111111111111111111111",
    "from": {
      "code": "BTC",
      "amount": "0.015",
      "address": "bc1q...",
      "txId": "deposit_tx_hash",
      "confirmations": 2
    },
    "to": {
      "code": "USDTTRC",
      "amount": "1543.42",
      "address": "TRON_DESTINATION_ADDRESS",
      "txId": null
    },
    "timeLeft": 840,
    "timeExpiration": 1770000000,
    "createdAt": "2026-05-20T00:33:25.000Z"
  }
}

Create safety

Create-order idempotency

Required integration rule for Bulk PSN

Send one unique, case-sensitive X-Idempotency-Key for every logical create. If the response is lost, retry with the same authenticated API key, the exact same header value, and the exact same request fields. Never generate a new key merely because a request timed out.

HeaderX-Idempotency-Reference
Returned whenAfter reservation
ContractStable provider reference in idem_<32 lowercase hex> format. It is also returned as client_reference in JSON and, when an order was created, in later order-status responses.
HeaderX-Idempotent-Replay
Returned whenStored replay only
ContractLiteral true when the response is a replay. The original HTTP status and JSON body are returned unchanged.
HeaderRetry-After
Returned whenProcessing 409 only
ContractValue is 2 seconds. Retry the exact same request and key; do not create a replacement request.
error_typeIDEMPOTENCY_KEY_REUSED
HTTP status409
Required client actionThe same scoped key has a different canonical request. Do not retry it with this body; investigate key reuse or use a new key only for a genuinely new logical order.
error_typeIDEMPOTENCY_REQUEST_IN_PROGRESS
HTTP status409
Required client actionThe matching request is unresolved. Wait at least Retry-After seconds, then retry the exact same key and body. Do not start another order.

Key format and scope

8-200 printable ASCII characters from ! through ~, with no spaces. Values are case-sensitive and scoped by authenticated apiKeyId plus key. The raw key is not persisted; the provider stores its SHA-256 digest.

Canonical request

The request hash covers every accepted create field, including submitted and resolved currency codes, direction, normalized numeric amount, destination address/tag, email, and client IP/time/timezone fields.

Reservation boundary

Malformed JSON, missing required fields, an invalid idempotency-key format, and a non-finite or non-positive amount are rejected before reservation. They have no client_reference and are not stored for replay. Once reserved, any completed validation, business, success, or server outcome is stored and replayed.

Same key and same request

No duplicate order is created. A completed request replays the stored original status and body, including stored business or server errors. An in-flight request waits briefly and replays if it completes.

Same key and different request

Returns deterministic HTTP 409 with code 4 and the original client_reference. Changing any canonical request field requires a new key for a genuinely new logical order.

Still processing

If the first execution is still unresolved after the wait window, the API returns HTTP 409, code 4, Retry-After: 2, and the stable client_reference. Keep retrying the same key/body or reconcile manually.

Legacy requests without the header

Remain accepted for backward compatibility but have legacy create behavior: each call may create a new order. Bulk PSN must not use this mode. Treat idempotency keys as permanently reserved and never reuse them.

Stored success replay

HTTP/1.1 200 OK
X-Idempotency-Reference: idem_11111111111111111111111111111111
X-Idempotent-Replay: true

{
  "code": 0,
  "data": {
    "orderNumber": "C4M2Q9",
    "token": "secure-order-token",
    "status": "NEW",
    "client_reference": "idem_11111111111111111111111111111111",
    "from": {
      "code": "BTC",
      "amount": "0.015",
      "address": "bc1q...",
      "tag": null,
      "txId": null
    },
    "to": {
      "code": "USDTTRC",
      "amount": "1543.42",
      "address": "TRON_DESTINATION_ADDRESS",
      "tag": null,
      "txId": null
    },
    "timeLeft": 1200,
    "timeExpiration": 1770000000
  }
}

Different request conflict

HTTP/1.1 409 Conflict
X-Idempotency-Reference: idem_11111111111111111111111111111111

{
  "code": 4,
  "error_type": "IDEMPOTENCY_KEY_REUSED",
  "error": "Idempotency key was already used with a different create-order request",
  "client_reference": "idem_11111111111111111111111111111111"
}

Still processing

HTTP/1.1 409 Conflict
X-Idempotency-Reference: idem_11111111111111111111111111111111
Retry-After: 2

{
  "code": 4,
  "error_type": "IDEMPOTENCY_REQUEST_IN_PROGRESS",
  "error": "Idempotency request is still processing; retry the same request with the same key",
  "client_reference": "idem_11111111111111111111111111111111"
}
Deployment note: this contract requires the additive provider database migration for idempotency records and order client references. Confirm that migration and application rollout are complete before enabling Bulk PSN production creates.

Runtime

Errors, statuses, and aliases

Error codes

Code0
MeaningSuccess. Read the data field.
Code1
MeaningValidation, disabled currency, min amount, invalid address, or provider business-rule error.
Code2
MeaningAuthentication failed. Check API credentials and headers.
Code3
MeaningOrder was not found.
Code4
MeaningIdempotency conflict or a matching create request is still processing. Read the HTTP 409 body and headers.
Code5
MeaningUnexpected server or upstream provider error. Retry safely or contact support with request context.

Order statuses

StatusNEW
MeaningOrder created and waiting for deposit.
StatusPENDING
MeaningDeposit detected or confirming.
StatusEXCHANGE
MeaningSwap is being processed.
StatusWITHDRAW
MeaningPayout transaction is being sent.
StatusDONE
MeaningOrder completed successfully.
StatusEXPIRED
MeaningDeposit window expired or the order cannot continue.
StatusREFUND
MeaningRefund handling is required or already in progress.

Alias compatibility

Accepted inputUSDTTRC
Internal codeUSDTTRC20
Accepted inputUSDTARBITRUM
Internal codeUSDTARB
Accepted inputUSDTAVAX
Internal codeUSDTAVAXC

Business error

{
  "code": 1,
  "error": "Minimum exchange amount: 0.0000127 BTC"
}

Compatibility

Legacy v1 routes

Keep these routes only for existing integrations that already rely on signed v1 requests. New partners should use /api/partner/*.

POST/api/v1/ccies

Legacy currency list with X-API-KEY / X-API-SIGN auth.

POST/api/v1/price

Legacy quote endpoint. Envelope: code / msg / data.

POST/api/v1/create

Legacy create endpoint. Supports clientIp body override.

POST/api/v1/order

Legacy order lookup by id and token in request body.

Need access or integration review?

Use support for API credentials, rollout questions, or contract verification.

Open support