Reference
Every environment variable, database column, admin endpoint, permission, cron job and Redis key the XT provider touches, with what breaks when each is wrong.
Everything the XT provider reads or writes, in one place. Where a value is dead — read by nothing that matters — it is marked as such, because a dead setting that looks live is worse than a missing one.
Environment variables
The variable names are derived, not hard-coded — the loader builds
APP_${provider.toUpperCase()}_API_KEY from the provider's name column, which
for this product is xt. Renaming the row would rename the variables.
The example .env carries NEXT_PUBLIC_EXCHANGE="bin" with a comment listing
five exchange aliases, which reads like a provider switch. It is not one. No
backend code reads it. Two frontend readers do:
- The TradingView chart component maps
binto Binance andkucto KuCoin, and everything else — includingxt— falls through to Binance symbols. - The market-data WebSocket service uses it to size the order-book depth the
browser requests.
xtselects XT's ladder (5 / 10 / 20 / 50 by tick size, the only depths XT serves); anything else asks for Binance's much deeper 40 / 80 / 160 / 320.
The active provider is the exchange row with status = true, and nothing else.
Changing this variable will not switch providers, and leaving it at bin will
not break an XT install — but it does mean the browser asks for depths XT will
not serve, so set it to "xt" and rebuild the frontend.
The provider row
The XT provider is one row in the exchange table, inserted by a seeder on every
install.
| Column | Value for XT | Notes |
|---|---|---|
name |
xt |
Passed to ccxt as the exchange id, and used to derive the env var names |
title |
XT |
Display name |
productId |
54510301 |
Licence key; also the .lic filename |
type |
spot |
|
status |
boolean | Exactly one exchange row may be true |
licenseStatus |
boolean | Re-synced from the .lic file on disk whenever the active provider is read |
version |
string | Never written by the seeder's update path |
proxyUrl |
nullable string | Per-provider proxy; masked when read back over the API |
link |
product URL |
productId carries a unique index, so no two providers can claim the same
licence.
Admin endpoints
Provider management
The status endpoint takes the row's id — a UUID. The provider update,
verify, test-proxy and activate endpoints take productId in the path
segment, though update and test-proxy in fact look the value up as an id. Copy
the identifier from the admin UI rather than assembling these URLs by hand.
Currencies, markets and charts
Licensing
Permissions
| Permission | Grants |
|---|---|
view.exchange |
Read the provider list and the active-provider screen |
edit.exchange |
Enable and disable providers, save the proxy, verify credentials, activate the provider licence |
view.exchange.market |
Read imported markets |
create.exchange.market |
Run the market import |
edit.exchange.market |
Edit a market's precision, limits and fees |
edit.ecosystem.market |
Enable or disable a market — single and bulk. Not an exchange.* key |
delete.exchange.market |
Delete a market |
edit.spot.currency |
Enable or disable spot currencies |
view.exchange.balance |
Read the platform's XT account balance |
view.exchange.fee |
Read collected fees |
view.exchange.chart / manage.exchange.chart |
Read and manage the candle cache |
view.spot.currency / create.spot.currency |
Read and import spot currencies |
create.license |
Activate and verify licences |
edit.exchange is the consequential one. It can switch the platform's entire
spot back-end to a different exchange, and — through the proxy field — redirect
every exchange call through a host of the grantee's choosing.
The two endpoints that toggle a market's status are gated on
edit.ecosystem.market, not edit.exchange.market, even though they live under
/api/admin/finance/exchange/market. A staff role built by granting every
exchange permission can import markets and edit their fees, and then gets a
permission error when it tries to enable one. Grant edit.ecosystem.market
alongside — it is required here whether or not the Ecosystem addon is installed.
Cron jobs
All three run on the cron worker and are no-ops when there is no active provider or when the ban switch is set.
| Job | Period | Effect if it stops |
|---|---|---|
processPendingSpotOrders |
60 s | Orders fill on XT but never settle in the platform; balances stay held |
processCurrenciesPrices |
120 s | Portfolio values freeze at their last known price |
processSpotPendingDeposits |
15 min | Pending SPOT deposits are never worked through |
Admin → System → Cron shows their last run, last error and next scheduled run.
Redis keys
| Key | Written by | Behaviour |
|---|---|---|
exchange:ban_status |
The rate-limit handler, and any error carrying IP banned until |
Holds the unblock time in epoch milliseconds. While set, every provider call returns without doing anything. Clamped to a maximum of 24 hours and given a matching TTL so it self-clears |
Nothing else deletes that key, and nothing in the admin UI shows it. If you need the spot stack back immediately after a ban, deleting it manually is the only lever — and only makes sense once XT has actually stopped throttling you.
XT's endpoints, for firewall rules
The server needs outbound HTTPS and WSS to:
| Host | Used for |
|---|---|
sapi.xt.com |
Spot REST — markets, currencies, orders, balances, deposits, withdrawals |
api.xt.com |
User endpoints |
stream.xt.com |
Spot WebSocket — tickers, candles, trades, order book |
fapi.xt.com and dapi.xt.com appear in ccxt's descriptor for futures and
inverse markets. This provider is spot only and does not use them.
Connection behaviour
Fixed values in the connection layer, none of them configurable:
| Behaviour | Value |
|---|---|
| Request timeout | 30 s |
| Rate limiting | Enabled — ccxt's own limiter, 100 ms between requests for XT |
| Receive window | 60 s |
| Clock safety margin | Signed requests are sent 500 ms behind XT's clock on purpose |
| Fallback clock offset | 1 s behind, used when fetchTime itself fails |
| Clock re-sync interval | 5 minutes, in the background, never blocking a caller |
| Init retries | 3, then a 30-minute cool-off after three consecutive failures |
| IP family | Forced to IPv4 unless a proxy is configured |
The clock handling exists because signed requests are rejected when the timestamp drifts. Keep NTP running on the server anyway — the platform biases the signature behind the server clock, but it cannot compensate for a clock that is minutes out.
Supported candle intervals
1m · 5m · 15m · 30m · 1h · 2h · 4h · 6h · 8h · 1d · 3d ·
1w · 1M
Capabilities used
XT supports every call this provider needs: fetchTime, fetchCurrencies,
fetchTickers, fetchOHLCV, fetchBalance, createOrder, fetchOrder,
fetchDepositAddress, fetchDeposits, fetchWithdrawals, withdraw, and the
WebSocket variants watchTickers, watchOHLCV, watchTrades and
watchOrderBook. Nothing in this product is disabled for XT on capability
grounds.