X-Trader Public API: what it does and how to authenticate
The X-Trader Public API v1.0.0 is a REST interface for managing the caller’s own sniper, copy-trade and transfer-snipe configurations, sniper and copy-trade templates, and a shared set of task labels. It never exposes wallet keys, trade exits, fund transfers or administrative capabilities. Every request is authenticated with a personal bearer token of the form xt_live_<public_id>.<secret>, and the account is derived from that token alone.
Primary source: X-Trader API reference. This page is an independent explanation of X-Trader Public API v1.0.0; it is not affiliated with X-Trader.
Scope of the API
Section titled “Scope of the API”| Managed by the API | Not available through the API |
|---|---|
Sniper configurations (/sniper/configs) |
Wallet private keys |
Copy-trade configurations (/copy-trade/configs) |
Executing or closing trades (exits) |
Transfer-snipe tasks (/transfer-snipe/configs), one watched wallet per task |
Fund transfers |
Sniper templates (/sniper/templates) |
Administrative functions |
Copy-trade templates (/copy-trade/templates) |
Native backend (Supabase) APIs |
Shared labels (/labels) |
Any other user’s resources |
Credential metadata (/me) |
Bulk delete |
There is no transfer-snipe template endpoint in v1.0.0. Configurations are always created paused and must be resumed explicitly (see write rules).
Base URL and transport
Section titled “Base URL and transport”| Item | Value |
|---|---|
| Base URL | https://x-trader.ai/api/v1 (the only server listed, marked Production) |
| Format | JSON request and response bodies |
| Auth header | Authorization: Bearer <token> on every request |
| Response envelope | {"data": ..., "meta": {"request_id": ...}} on success, {"error": ..., "request_id": ...} on failure |
Write responses carry meta.persistence = "committed" (the database write finished) and meta.propagation = "eventual" (execution nodes pick the change up shortly after).
Token format and creation
Section titled “Token format and creation”The security scheme is HTTP bearer with bearerFormat xt_live_<public_id>.<secret>.
| Part | Meaning |
|---|---|
xt_live_ |
Fixed prefix for live tokens |
<public_id> |
Non-secret identifier. GET /me returns it as token_prefix, matching ^xt_live_[a-f0-9]{8}$ (8 lowercase hex characters) |
. |
Separator |
<secret> |
Secret part. Shown only once |
Tokens are created in the X-Trader web app under Settings, Developer API. The documented setup steps are:
- Sign in and open the Developer API settings.
- Select only the scopes the integration needs.
- Add an IP allowlist and an expiration date whenever possible.
- Copy the token into a server-side secret store immediately; X-Trader cannot show it again.
- Call
GET /meto verify it.
The spec advises keeping tokens in trusted server-side code only: never in browser JavaScript, mobile bundles, URLs, logs, Git repositories or third-party proxies.
Scopes
Section titled “Scopes”A token carries up to 9 scopes. Each operation declares a required scope.
| Scope | Allows |
|---|---|
sniper:read |
List and get sniper configs and sniper templates; list and get labels |
sniper:write |
Create, update, pause and resume sniper configs; create and update sniper templates; create, update and delete labels |
sniper:delete |
Delete sniper configs and sniper templates |
copytrade:read |
List and get copy-trade configs and copy-trade templates; list and get labels |
copytrade:write |
Create, update, pause and resume copy-trade configs; create and update copy-trade templates; create, update and delete labels |
copytrade:delete |
Delete copy-trade configs and copy-trade templates |
transfersnipe:read |
List and get transfer-snipe tasks |
transfersnipe:write |
Create, update, pause and resume transfer-snipe tasks |
transfersnipe:delete |
Delete transfer-snipe tasks |
Notes derived from the per-operation requirements:
- Label endpoints accept either the sniper or the copy-trade scope (
sniper:readorcopytrade:readfor reads,sniper:writeorcopytrade:writefor writes, includingDELETE /labels/{id}). The spec does not list anytransfersnipe:*scope for label endpoints, so a token with only transfer-snipe scopes cannot manage labels. - Deleting a label needs a
:writescope, not a:deletescope. GET /medeclares no specific scope; any valid token can call it.- A call without the required scope fails with
insufficient_scope(see errors).
GET /me
Section titled “GET /me”GET /me returns metadata about the credential used for the request. It returns no internal user identifier. It is the recommended first call after creating or rotating a token.
| Field | Type | Description |
|---|---|---|
token_prefix |
string, ^xt_live_[a-f0-9]{8}$ |
Non-secret identifier of this credential |
token_version |
integer, greater than 0 | Credential version; rotation increments it |
scopes |
array of scope strings (max 9) | Exact permissions granted to this token |
expires_at |
date-time or null |
Expiry timestamp; null means the token does not expire |
quota.max |
integer | Maximum number of configurations for the account |
quota.used |
integer | Current number of sniper, copy-trade and transfer-snipe configurations combined |
quota.remaining |
integer | Configurations that can still be created |
login_username |
string or null (default null) |
Login name of the account; the spec gives no further description |
family_role |
enum none, primary, member (default none) |
Account family role; the spec gives no further description |
The quota is shared: sniper, copy-trade and transfer-snipe configurations all count against the same max. Templates and labels have their own separate limits (1,000 templates shared by sniper and copy-trade, 20 labels).
export X_TRADER_API_TOKEN='xt_live_xxxxxxxx.your_secret'
curl 'https://x-trader.ai/api/v1/me' \ --header "Authorization: Bearer $X_TRADER_API_TOKEN"import osimport requests
BASE = "https://x-trader.ai/api/v1"headers = {"Authorization": f"Bearer {os.environ['X_TRADER_API_TOKEN']}"}
r = requests.get(f"{BASE}/me", headers=headers, timeout=10)r.raise_for_status()me = r.json()["data"]print(me["token_prefix"], me["scopes"])print("quota remaining:", me["quota"]["remaining"], "of", me["quota"]["max"])IP allowlist and expiry
Section titled “IP allowlist and expiry”A token can be restricted to an IP allowlist and given an expiration date when it is created. The spec recommends both. A request from an address outside the allowlist is rejected with ip_not_allowed. The expiry is visible in expires_at. The spec does not document the allowlist format, whether these settings can be edited after creation, or which error code an expired token returns. As practical guidance, treat invalid_api_token as the likely result for a token that is no longer accepted and check expires_at proactively.
Rotation and revocation
Section titled “Rotation and revocation”- Rotate or revoke the token immediately if exposure is suspected.
- Rotation invalidates the previous token at once; there is no grace period in the documented behaviour.
- After rotation,
token_versionis incremented. CallGET /mewith the new token to confirm it.
Rotation and revocation are performed in the web app; the API has no endpoint for them.
Identity and ownership isolation
Section titled “Identity and ownership isolation”- No request body, query parameter or path accepts
user_id; sending it in a body is rejected. - Every list returns only the token owner’s resources.
- A config, template or label id that belongs to another account returns
404 not_found, exactly like a missing id. This also applies to a foreignrisk_label_idin a request body and a foreignlabel_idlist filter.
Endpoint map
Section titled “Endpoint map”| Method and path | Scope | Purpose | Page |
|---|---|---|---|
GET /me |
any | Credential metadata and shared quota | this page |
GET /sniper/configs |
sniper:read |
List sniper configs | sniper |
POST /sniper/configs |
sniper:write |
Create a paused sniper config | sniper |
GET /sniper/configs/{id} |
sniper:read |
Get one sniper config | sniper |
PATCH /sniper/configs/{id} |
sniper:write |
Update a sniper config | sniper |
DELETE /sniper/configs/{id} |
sniper:delete |
Delete a paused sniper config | sniper |
POST /sniper/configs/{id}/pause |
sniper:write |
Pause | sniper |
POST /sniper/configs/{id}/resume |
sniper:write |
Revalidate and resume | sniper |
GET, POST /copy-trade/configs |
copytrade:read, copytrade:write |
List, create | copy-trade |
GET, PATCH, DELETE /copy-trade/configs/{id} |
copytrade:read, :write, :delete |
Get, update, delete | copy-trade |
POST /copy-trade/configs/{id}/pause, /resume |
copytrade:write |
Pause, resume | copy-trade |
GET, POST /transfer-snipe/configs |
transfersnipe:read, transfersnipe:write |
List, create | transfer-snipe |
GET, PATCH, DELETE /transfer-snipe/configs/{id} |
transfersnipe:read, :write, :delete |
Get, update, delete | transfer-snipe |
POST /transfer-snipe/configs/{id}/pause, /resume |
transfersnipe:write |
Pause, resume | transfer-snipe |
GET, POST /sniper/templates |
sniper:read, sniper:write |
List, create | templates |
GET, PATCH, DELETE /sniper/templates/{id} |
sniper:read, :write, :delete |
Get, update, delete | templates |
GET, POST /copy-trade/templates |
copytrade:read, copytrade:write |
List, create | templates |
GET, PATCH, DELETE /copy-trade/templates/{id} |
copytrade:read, :write, :delete |
Get, update, delete | templates |
GET, POST /labels |
sniper:* or copytrade:* read / write |
List, create | labels |
GET, PATCH, DELETE /labels/{id} |
read / write | Get, update, delete | labels |
Related reference pages: write rules, errors, pagination, and the config field references sniper config, copy-trade config, auto-sell, auto strategy, timed strategy.
What can the X-Trader Public API change?
Section titled “What can the X-Trader Public API change?”Only the caller’s own sniper, copy-trade and transfer-snipe configurations, sniper and copy-trade templates, and shared labels. Wallet keys, trade exits, fund transfers and administrative functions are not exposed.
What does an X-Trader API token look like?
Section titled “What does an X-Trader API token look like?”A personal token has the form xt_live_<public_id>.<secret> and is sent as Authorization: Bearer <token>. The full token is shown once at creation and cannot be recovered.
Which call should I make first?
Section titled “Which call should I make first?”GET /me. It confirms the token works and returns its prefix, version, scopes, expiry and the shared configuration quota.
Why does a config id from another account return 404?
Section titled “Why does a config id from another account return 404?”The user is derived only from the token. An id owned by someone else returns the same 404 not_found as an id that does not exist, so existence is never disclosed.
What happens to the old token when I rotate it?
Section titled “What happens to the old token when I rotate it?”Rotation invalidates the previous token immediately and increments token_version. Update every client before or right after rotating.