FreedomSwap API
One key ID and one secret. One executable rate.
Add cross-chain swaps and permanent conversion addresses to any wallet or service. FreedomSwap returns one executable quote for each supported request.
- Environment
- Production
- Base URL
https://xchgo.com/api/v1- Authentication
- Backend-only key ID + shared secret
- Quote response
- One selected executable rate
- Specification
- OpenAPI 3.1 · v1.8
- 01ProvisionStore the key ID and shared secret on your backend.
- 02DiscoverCache assets by ticker and network.
- 03QuoteRequest the best eligible rate.
- 04Create & trackUse the quote ID and canonical status.
Quickstart
Use the Node SDK from your backend. It authenticates each request with your key ID and shared secret.
// Download from https://xchgo.com/sdk/freedomswap-client.mjs
import { createFreedomSwapClient } from "./freedomswap-client.mjs";
// Server-side only. Never embed either credential in an app or website.
const freedomSwap = createFreedomSwapClient({
baseUrl: process.env.FREEDOMSWAP_API_BASE,
keyId: process.env.FREEDOMSWAP_KEY_ID,
sharedSecret: process.env.FREEDOMSWAP_SHARED_SECRET,
userId: customer.id
});Production base URL: https://xchgo.com/api/v1. The SDK also accepts the origin https://xchgo.com.
Authentication
You receive a public key ID and a secret. Keep the secret on your backend and pass an opaque userId for each customer or wallet record. The SDK handles timestamped, replay-protected request signing automatically.
To request or rotate a production credential, contact support@xchgo.com.
Load assets and pair guidance
Call GET /api/v1/assets for supported asset and network combinations. Treat the asset and network as one identifier. GET /api/v1/pairs provides compact pair guidance and platform limits. To load destinations for a selected source, call GET /api/v1/pairs?sourceAsset=BTC&sourceNetwork=BTC with both query parameters. Request a quote to confirm an exact pair and amount.
const response = await fetch(
`${FREEDOMSWAP_API_BASE}/assets`
);
const { assets } = await response.json();Request the selected quote
Use best or omit rateType for the normal flow. FreedomSwap returns one executable quote. Advanced callers may request fixed or floating.
Display the returned amount and use the quote ID before it expires.
const { quote } = await freedomSwap.quote({
sourceAsset: "BTC",
sourceNetwork: "BTC",
destinationAsset: "ETH",
destinationNetwork: "ETH",
sourceAmount: "0.01",
rateType: "best",
refundMode: "sender"
});{
"quote": {
"id": "2adf1a8b-40d1-4c44-9c1d-4d24aa53e82f",
"sourceAmount": "0.01",
"depositAmount": "0.01",
"receiveAmount": "0.331787",
"rate": "33.1787",
"rateType": "fixed",
"minimumSourceAmount": "0.00015",
"maximumSourceAmount": null,
"expiresAt": "2026-08-13T12:05:00.000Z"
}
}quote.id- Pass this exact ID to swap creation before it expires.
quote.rateType- Use this value when creating the swap.
quote.expiresAt- Request a new quote after this time.
expiresAt and request a new quote after expiry.Create a swap
Create using the same pair, amount, rate type, and returned quote ID. FreedomSwap validates the destination and refund policy again. HTTP 202 means creation was queued; it does not mean the customer may deposit yet.
const { order, accessToken } = await freedomSwap.createSwap({
sourceAsset: "BTC",
sourceNetwork: "BTC",
destinationAsset: "ETH",
destinationNetwork: "ETH",
sourceAmount: "0.01",
destinationAddress: customer.ethAddress,
rateType: quote.rateType,
refundMode: "sender",
quoteId: quote.id
});{
"order": {
"id": "6e2ae41c-51fa-4db7-a33e-9c6259c22827",
"status": "waiting",
"depositAddress": null,
"sourceAmount": "0.01",
"expectedOutputAmount": "0.331787"
},
"accessToken": "swap-scoped-status-token"
}depositAddress. Never fabricate, cache from another order, or display a funding address while this field is null.Track the transaction
The backend SDK can read swaps it created. A customer device may instead receive the swap-scoped access token for that swap and its event stream.
const current = await freedomSwap.getSwap(order.id);
// Or give a customer device only the swap-scoped token:
const currentByToken = await freedomSwap.getSwapByAccessToken(
order.id,
accessToken
);
if (currentByToken.order.depositAddress) {
showDepositAddress(currentByToken.order.depositAddress);
}For push-style updates, connect to GET /api/v1/swaps/{id}/stream with the access token. The server closes the event stream on a terminal status or when the swap requires review.
Canonical status values
All swaps use one public status vocabulary. Build your UI against these values.
waitingAccepted and waiting for a usable deposit address or customer funding.confirmingA deposit was detected and is waiting for the required confirmations.exchangingConfirmed funds are being converted.sendingThe destination payout is being prepared, broadcast, or confirmed.accumulatingA reusable-route deposit is below the executable minimum and is being combined with later deposits.finishedThe destination payout completed successfully. Terminal.refundedFunds were returned according to the order refund policy. Terminal.failedThe swap cannot continue automatically. Terminal; use the support context on the order.expiredThe order or funding window expired before execution. Terminal.overdueThe expected completion window passed and automated processing stopped. Terminal.reviewThe swap needs review. Check its latest event or contact support.Endpoint summary
GET/api/v1/healthRead service availability.GET/api/v1/assetsGet supported assets and networks.GET/api/v1/pairsGet pair guidance and platform limits for a selected source.POST/api/v1/quotesReturn one executable quote.POST/api/v1/swapsCreate a swap from an unexpired quote ID.GET/api/v1/swaps/{id}Track one swap with backend authentication or its access token.GET/api/v1/swaps/{id}/streamStream status changes with the swap access token.POST/api/v1/permanent-routes/challengesStart settlement-wallet ownership proof.POST/api/v1/permanent-routesCreate or recover a destination-bound reusable route.GET/api/v1/permanent-routesList reusable routes owned by this partner and user.GET/api/v1/permanent-routes/{id}Read one owned route and its persistent source addresses.GET/api/v1/permanent-routes/{id}/depositsRead detected deposits and the swap each became.POST/api/v1/permanent-routes/{id}/expect-depositNotify FreedomSwap before an expected deposit.The machine-readable schemas and full route list are in the OpenAPI 3.1 document.
Errors and retries
Request errors use { "error": { "code": "…", "message": "…" } }. The health endpoint returns its service-status payload. For 429, respect Retry-After.
400invalid inputCorrect the request. Do not retry unchanged.401/403authentication failedCheck the credential and request.409pair, amount, rate type, or quote unavailableRefresh the pair catalogue or request a fresh quote.429rate limit exceededRetry with exponential backoff and jitter.500/502/503service unavailableRetry safely with backoff; never invent a rate or deposit address.Retry only idempotent reads automatically. For an uncertain create response, check your recorded order before trying again; do not create multiple customer funding addresses blindly.
Permanent conversion routes
Reusable routes provide persistent deposit addresses for a verified settlement wallet. Complete an ownership challenge, then create the route.
POST /api/v1/permanent-routes/challenges- Sign or verify the returned challenge for the settlement address.
POST /api/v1/permanent-routes- List deposits at
GET /api/v1/permanent-routes/{id}/deposits.
The same partner user and verified destination recover the existing route. Returned source addresses remain reusable. Call POST /api/v1/permanent-routes/{id}/expect-deposit before an expected payment, and read deposits from the route deposits endpoint.
accumulated_usd, remaining_usd, and valued_at; no service fee or gas allowance is charged until that same asset can execute once as a combined amount.Integration support
Start with this guide, the OpenAPI document, and the downloadable Node SDK. Contact support@xchgo.com for credential provisioning or production integration questions—never include keys, wallet recovery phrases, or customer secrets.