Skip to content

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.

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).

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).

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:

  1. Sign in and open the Developer API settings.
  2. Select only the scopes the integration needs.
  3. Add an IP allowlist and an expiration date whenever possible.
  4. Copy the token into a server-side secret store immediately; X-Trader cannot show it again.
  5. Call GET /me to 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.

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:read or copytrade:read for reads, sniper:write or copytrade:write for writes, including DELETE /labels/{id}). The spec does not list any transfersnipe:* scope for label endpoints, so a token with only transfer-snipe scopes cannot manage labels.
  • Deleting a label needs a :write scope, not a :delete scope.
  • GET /me declares no specific scope; any valid token can call it.
  • A call without the required scope fails with insufficient_scope (see errors).

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).

Terminal window
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 os
import 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"])

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.

  • 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_version is incremented. Call GET /me with the new token to confirm it.

Rotation and revocation are performed in the web app; the API has no endpoint for them.

  • 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 foreign risk_label_id in a request body and a foreign label_id list filter.
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.

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.

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.