Skip to content

X-Trader labels API

X-Trader labels are a per-account set of up to 20 named, coloured tags shared by sniper, copy-trade and transfer-snipe tasks. They are managed at /labels (list, create, get, update, delete) and bound to tasks through the risk_label_id field. Label names are unique per account, labels do not use ETag/If-Match, and templates never take a label.

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.

Method and path Required scope Headers Success
GET /labels sniper:read or copytrade:read Authorization 200, all labels
POST /labels sniper:write or copytrade:write Authorization, Idempotency-Key 201, created label
GET /labels/{id} sniper:read or copytrade:read Authorization 200, one label
PATCH /labels/{id} sniper:write or copytrade:write Authorization 200, updated label
DELETE /labels/{id} sniper:write or copytrade:write Authorization 204, empty

Either product scope is sufficient. The spec lists no transfersnipe:* scope for label endpoints, even though transfer-snipe tasks can be labelled, so a transfer-snipe-only token cannot manage labels. Deletion uses a :write scope; there is no label :delete scope. Responses carry X-Request-Id but no ETag.

Field Type Meaning
id UUID Server-generated label id
name string, 1-32 characters Display name, trimmed
color string, ^#[0-9A-Fa-f]{6}$ Colour as #RRGGBB
sort_order integer Display order (0-32767 on input)
sniper_count integer, 0 or more Sniper configs using this label
copy_trade_count integer, 0 or more Copy-trade configs using this label
transfer_snipe_count integer, 0 or more Transfer-snipe tasks using this label
created_at ISO 8601 date-time with UTC offset Creation time
updated_at ISO 8601 date-time with UTC offset Last change
Field Type Default Constraints
name string none 1-32 characters after trimming leading and trailing spaces; unique per account
color string #6366f1 #RRGGBB
sort_order integer 0 0-32767

The schema lists all three as required while also giving defaults for color and sort_order; the spec’s own curl example sends only name and color. Sending all three avoids any ambiguity.

Any of name, color, sort_order with the same constraints; at least one field is required. Unknown fields and user_id are rejected with validation_error.

Rule Behaviour
Maximum labels per account 20; the 21st create returns quota_exceeded
Unique names Duplicate name on create or PATCH returns label_name_exists
Shared set One set for sniper, copy-trade and transfer-snipe tasks
List order sort_order, then created_at
Pagination None; GET /labels returns all labels in data.items
Concurrency No ETag / If-Match on labels; last write applies
Idempotency Idempotency-Key required on POST /labels (8-128 chars, A-Za-z0-9._:-, kept 24 h)
Renaming Bound tasks keep the same label id
Delete Tasks are unassigned (ON DELETE SET NULL), not deleted
Foreign id Label owned by another account returns 404 not_found

Binding labels to tasks with risk_label_id

Section titled “Binding labels to tasks with risk_label_id”

Sniper, copy-trade and transfer-snipe configs have a nullable risk_label_id field.

Action How
Bind on create Include "risk_label_id": "<label uuid>" in the create body
Change binding PATCH /{product}/configs/{id} with risk_label_id and the current If-Match
Remove binding PATCH with "risk_label_id": null and the current If-Match
Filter lists GET /{product}/configs?label_id=<uuid> or label_id=unlabeled

Binding or clearing a label is allowed while the task is active; only config and linked_wallets changes require pausing. The request still needs the latest If-Match. A risk_label_id that does not exist or belongs to another account returns 404 not_found.

Templates never accept or return risk_label_id; sending it in a template body is rejected. Labels are applied per task, not per template.

Create a label:

Terminal window
curl --request POST 'https://x-trader.ai/api/v1/labels' \
--header "Authorization: Bearer $X_TRADER_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: label-create-001' \
--data '{"name":"Watchlist","color":"#6366f1","sort_order":0}'

Rename and recolour (no If-Match):

Terminal window
curl --request PATCH "https://x-trader.ai/api/v1/labels/$LABEL_ID" \
--header "Authorization: Bearer $X_TRADER_API_TOKEN" \
--header 'Content-Type: application/json' \
--data '{"name":"High priority","color":"#ef4444"}'

Bind the label to a sniper config:

Terminal window
curl --request PATCH "https://x-trader.ai/api/v1/sniper/configs/$CONFIG_ID" \
--header "Authorization: Bearer $X_TRADER_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'If-Match: "v3"' \
--data "{\"risk_label_id\":\"$LABEL_ID\"}"

Delete a label:

Terminal window
curl --request DELETE "https://x-trader.ai/api/v1/labels/$LABEL_ID" \
--header "Authorization: Bearer $X_TRADER_API_TOKEN"

Python: get or create a label by name, then bind it:

import os
import uuid
import requests
BASE = "https://x-trader.ai/api/v1"
H = {"Authorization": f"Bearer {os.environ['X_TRADER_API_TOKEN']}"}
def get_or_create_label(name, color="#6366f1"):
r = requests.get(f"{BASE}/labels", headers=H, timeout=10)
r.raise_for_status()
for label in r.json()["data"]["items"]:
if label["name"] == name:
return label
r = requests.post(
f"{BASE}/labels",
headers={**H, "Idempotency-Key": f"label-{uuid.uuid4()}"},
json={"name": name, "color": color, "sort_order": 0},
timeout=10,
)
r.raise_for_status() # quota_exceeded once 20 labels exist
return r.json()["data"]
def bind_label(product, config_id, label_id):
r = requests.get(f"{BASE}/{product}/configs/{config_id}", headers=H, timeout=10)
r.raise_for_status()
r = requests.patch(
f"{BASE}/{product}/configs/{config_id}",
headers={**H, "If-Match": r.headers["ETag"]},
json={"risk_label_id": label_id}, # None to unassign
timeout=10,
)
r.raise_for_status()
return r.json()["data"]
label = get_or_create_label("Watchlist")
bind_label("copy-trade", "00000000-0000-4000-8000-000000000000", label["id"])

How many labels can an X-Trader account have?

Section titled “How many labels can an X-Trader account have?”
  1. Creating the 21st label returns quota_exceeded. Sniper, copy-trade and transfer-snipe tasks share this one set.

No. Names are unique per account; creating or renaming to an existing name returns label_name_exists.

No. Labels do not use ETag or If-Match. Creating a label still requires an Idempotency-Key header.

Send risk_label_id with the label UUID when creating a config, or in a PATCH with the config’s current If-Match. Send risk_label_id=null to remove it. The task does not need to be paused.

What happens to tasks when I delete a label?

Section titled “What happens to tasks when I delete a label?”

They are not deleted. Their risk_label_id is set to null (ON DELETE SET NULL).