X-Trader transfer-snipe API
A transfer-snipe task is a user-scoped X-Trader task that watches one wallet (the spec calls it watch wallet A, one per task) and carries a buy and sell strategy whose config schema is identical to the sniper config. It is managed through seven operations under /transfer-snipe/configs with the transfersnipe:read, transfersnipe:write and transfersnipe:delete scopes. Like sniper and copy-trade tasks, it is always created paused and runs only after POST /transfer-snipe/configs/{id}/resume.
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.
What the spec says about transfer-snipe
Section titled “What the spec says about transfer-snipe”- The tag description defines a transfer-snipe task as having one watch wallet A per task, with creation paused by design.
- The only wallet field in the request body is
target_wallet, so that field holds wallet A. It is a single Solana address and is immutable after creation. TransferSnipeCreatestates that its config shape matches sniper; theconfigschemas ofSniperCreateandTransferSnipeCreateare the same.- Transfer-snipe tasks share the label set with sniper and copy-trade (
LabelResource.transfer_snipe_count) and count toward the same configuration quota reported byGET /me.
The spec does not document which on-chain transfer events from wallet A trigger a buy, nor how the purchased token is chosen. It also defines no transfer-snipe templates.
Operations
Section titled “Operations”| Method and path | Purpose | Scope | Required headers | Success |
|---|---|---|---|---|
GET /transfer-snipe/configs |
List owned tasks | transfersnipe:read |
Authorization |
200 list envelope |
POST /transfer-snipe/configs |
Create a paused task | transfersnipe:write |
Authorization, Idempotency-Key |
201 resource envelope |
GET /transfer-snipe/configs/{id} |
Read one task | transfersnipe:read |
Authorization |
200 resource envelope |
PATCH /transfer-snipe/configs/{id} |
Update mutable fields | transfersnipe:write |
Authorization, If-Match |
200 resource envelope |
DELETE /transfer-snipe/configs/{id} |
Delete a paused task | transfersnipe:delete |
Authorization, If-Match |
204 no body |
POST /transfer-snipe/configs/{id}/pause |
Stop execution | transfersnipe:write |
Authorization, If-Match |
200 resource envelope |
POST /transfer-snipe/configs/{id}/resume |
Revalidate and start | transfersnipe:write |
Authorization, If-Match |
200 resource envelope |
Base URL https://x-trader.ai/api/v1. Error statuses listed for every operation: 400, 401, 403, 404, 409, 429, 500, 503. No bulk delete.
Headers
Section titled “Headers”| Header | Where | Rule |
|---|---|---|
Authorization |
All | Bearer xt_live_<id>.<secret> |
Idempotency-Key |
Create | 8-128 chars, A-Z a-z 0-9 . _ : -, retained 24 hours; reuse with another body gives idempotency_conflict |
If-Match |
PATCH, DELETE, pause, resume | Latest ETag, "v<number>"; stale gives version_conflict |
ETag (response) |
201/200 single-resource | Send as If-Match next time |
X-Request-Id (response) |
Single-resource and delete | Support correlation |
Shared write rules: /xtrader/write-rules/.
List: GET /transfer-snipe/configs
Section titled “List: GET /transfer-snipe/configs”| Query parameter | Type | Rule |
|---|---|---|
limit |
integer | 1-100, default 20 |
cursor |
string | Max 2048; opaque next_cursor, bound to token and filters |
status |
string | active or paused |
q |
string | Max 64; searches remark and target_wallet |
label_id |
string | Owned label UUID or unlabeled; foreign or missing UUID returns 404 |
Ordering is by updated_at and id. Response: data.items, data.next_cursor, meta.request_id. See /xtrader/pagination/.
TransferSnipeCreate fields
Section titled “TransferSnipeCreate fields”Top level (strict; user_id, version, template and unknown fields are rejected):
| Field | Type | Required | Default | Constraint |
|---|---|---|---|---|
remark |
string | yes | "" |
Max 64 characters, trimmed |
target_wallet |
string | yes | Watch wallet A. Solana address, 32-44 characters, immutable | |
risk_label_id |
string (UUID) or null | no | Label owned by the account; null unassigns; foreign ID returns 404 |
|
config |
object | yes | Complete strategy, schema below |
config (same schema as the sniper config; full reference at /xtrader/config-sniper/):
| Field | Type | Required | Default | Constraint and meaning |
|---|---|---|---|---|
buy_amount |
decimal string | yes | SOL per buy, greater than 0 and at most 1,000,000 | |
jito_mode |
object | yes | Jito route fees: tip_amount (0-1,000 SOL), priority_fee (0-1,000 SOL), slippage (0-100 %) required; optional bundle_amount, sol_slippage_mode |
|
priority_mode |
object | yes | Leader/direct route fees, same keys and ranges as jito_mode |
|
bundle_amount |
decimal string | no | Legacy top-level fallback; prefer the copy inside jito_mode / priority_mode |
|
selected_dexes |
array | yes | 1-5 of pump-fun, launchlab, believe, bags, meteora-dynamic-bc |
|
dex_source |
string | yes | global |
global uses the enabled global DEX list (falls back to selected_dexes); config always uses selected_dexes |
dev_min_amount |
decimal string | no | Lower bound of the creator buy filter; "" disables it |
|
dev_max_amount |
decimal string | no | Upper bound; "" disables it; must be at least dev_min_amount when both are set |
|
buy_once |
boolean | yes | false |
Deactivate the task after its first triggered trade |
sol_slippage_mode |
boolean | yes | false |
Legacy shared SOL-slippage flag; per-mode flags take precedence |
snipe_external |
boolean | yes | false |
Skip the bonding curve and use supported external-pool execution only |
auto_sell |
object | yes | TP, SL, trailing TP, follow-sell; see /xtrader/auto-sell/ | |
auto_strategy |
object | yes | Migration, timed sell, protections, sell-fee override; see /xtrader/auto-strategy/ | |
timed_strategy |
object | yes | Up to 20 delayed sell orders; see /xtrader/timed-strategy/ |
All amounts, fees, percentages and durations are decimal strings (at most 12 fractional digits, max 32 characters), never JSON numbers. Every nested object is strict.
TransferSnipeResource adds the server fields id, is_active, version, created_at and updated_at, and returns remark, target_wallet, risk_label_id and config.
Create
Section titled “Create”curl --request POST 'https://x-trader.ai/api/v1/transfer-snipe/configs' \ --header "Authorization: Bearer $X_TRADER_API_TOKEN" \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: create-transfer-20261016-001' \ --data '{ "remark": "Watch wallet A", "target_wallet": "11111111111111111111111111111111", "config": { "buy_amount": "0.1", "jito_mode": {"tip_amount": "0.01", "priority_fee": "0.0005", "slippage": "15", "bundle_amount": ""}, "priority_mode": {"tip_amount": "0.001", "priority_fee": "0.005", "slippage": "15", "bundle_amount": ""}, "selected_dexes": ["pump-fun"], "dex_source": "global", "dev_min_amount": "", "dev_max_amount": "", "buy_once": false, "sol_slippage_mode": false, "snipe_external": false, "auto_sell": { "enabled": false, "tab": "tpsl", "expiry_time": "10", "tp_orders": [{"trigger": "90", "sell": "100"}], "sl_orders": [], "follow_sell": false, "proportional_sell": false, "trailing_take_profit": {"enabled": false, "tiers": []} }, "auto_strategy": {"migration_clear": false, "timed_sell": false, "sell_delay": "30"}, "timed_strategy": {"enabled": false, "orders": []} } }'Response 201 Created (headers ETag: "v1", X-Request-Id; IDs and timestamps illustrative):
{ "data": { "id": "c4e7a2b0-91d3-4f5e-a6b8-0d2c9e1f3a75", "remark": "Watch wallet A", "target_wallet": "11111111111111111111111111111111", "is_active": false, "risk_label_id": null, "version": 1, "created_at": "2026-10-16T09:00:00Z", "updated_at": "2026-10-16T09:00:00Z", "config": { "buy_amount": "0.1", "...": "stored config as sent" } }, "meta": { "request_id": "req_0123456789abcdef", "persistence": "committed", "propagation": "eventual" }}Get, patch, delete
Section titled “Get, patch, delete”GET /transfer-snipe/configs/{id}: missing and foreign IDs both return404 not_found. The stored snapshot is returned as is, possibly with legacy fields.PATCH /transfer-snipe/configs/{id}(TransferSnipePatch): at least one ofremark,risk_label_id,config. While active, onlyremarkandrisk_label_idmay change; pause before changingconfig. Aconfigin the patch replaces the whole stored config and must pass the full schema.target_walletcannot be patched. The operation text also mentionslinked_wallets, butTransferSnipePatchhas no such field and unknown fields are rejected.DELETE /transfer-snipe/configs/{id}: only paused tasks;204on success.
Pause and resume
Section titled “Pause and resume”Pause updates the stored state immediately; execution nodes pick it up eventually. Resume revalidates the complete stored config before activation and will not activate invalid historical data.
curl --request POST 'https://x-trader.ai/api/v1/transfer-snipe/configs/c4e7a2b0-91d3-4f5e-a6b8-0d2c9e1f3a75/resume' \ --header "Authorization: Bearer $X_TRADER_API_TOKEN" \ --header 'If-Match: "v1"'Response 200 OK with the new ETag header (values illustrative):
{ "data": { "id": "c4e7a2b0-91d3-4f5e-a6b8-0d2c9e1f3a75", "remark": "Watch wallet A", "target_wallet": "11111111111111111111111111111111", "is_active": true, "risk_label_id": null, "version": 2, "created_at": "2026-10-16T09:00:00Z", "updated_at": "2026-10-16T09:01:10Z", "config": { "buy_amount": "0.1", "...": "unchanged stored config" } }, "meta": { "request_id": "req_0123456789abcdef", "persistence": "committed", "propagation": "eventual" }}Python: pause, change buy amount, resume
Section titled “Python: pause, change buy amount, resume”import osimport requests
BASE = "https://x-trader.ai/api/v1"H = {"Authorization": f"Bearer {os.environ['X_TRADER_API_TOKEN']}"}tid = "c4e7a2b0-91d3-4f5e-a6b8-0d2c9e1f3a75"
r = requests.get(f"{BASE}/transfer-snipe/configs/{tid}", headers=H)r.raise_for_status()task, etag = r.json()["data"], r.headers["ETag"]
if task["is_active"]: r = requests.post(f"{BASE}/transfer-snipe/configs/{tid}/pause", headers={**H, "If-Match": etag}) r.raise_for_status() etag = r.headers["ETag"]
config = task["config"] # full object: PATCH replaces config completelyconfig["buy_amount"] = "0.2" # decimal string, not a number
r = requests.patch(f"{BASE}/transfer-snipe/configs/{tid}", json={"config": config}, headers={**H, "If-Match": etag})r.raise_for_status()
r = requests.post(f"{BASE}/transfer-snipe/configs/{tid}/resume", headers={**H, "If-Match": r.headers["ETag"]})r.raise_for_status()If the stored snapshot contains legacy web-UI fields, the PATCH or resume can fail with validation_error; remove the fields listed in error.fields and send a config that matches the current schema.
Lifecycle
Section titled “Lifecycle”- Create (paused) with an
Idempotency-Key. - Resume with the
ETagfrom the create response. - To change the strategy: pause, PATCH the full
config, resume. remarkandrisk_label_idcan change without pausing (still withIf-Match).- To remove: pause, then delete.
Errors
Section titled “Errors”Error body: { "error": { "code", "message", "fields"? }, "request_id" }.
| Code | Typical cause on /transfer-snipe/configs |
|---|---|
validation_error |
Unknown field, number instead of decimal string, empty PATCH, failed resume revalidation |
insufficient_scope |
Token lacks the needed transfersnipe:* scope |
not_found |
Unknown or foreign task ID, foreign label |
config_must_be_paused |
config change or delete while active |
version_conflict |
Stale If-Match |
idempotency_required / idempotency_conflict |
Missing key, or key reused with another body |
quota_exceeded |
Shared configuration quota full |
rate_limit_exceeded, service_unavailable |
429 / 503 with Retry-After |
The spec does not say whether target_already_exists applies to transfer-snipe. Full list: /xtrader/errors/.
What is a transfer-snipe task in the X-Trader API?
Section titled “What is a transfer-snipe task in the X-Trader API?”It is a user-scoped task with exactly one watch wallet (wallet A), stored in target_wallet, plus a strategy config whose shape matches the sniper config. Like other tasks it is created paused.
Which scopes does transfer-snipe use?
Section titled “Which scopes does transfer-snipe use?”transfersnipe:read for list and get, transfersnipe:write for create, patch, pause and resume, and transfersnipe:delete for delete.
Can one transfer-snipe task watch several wallets?
Section titled “Can one transfer-snipe task watch several wallets?”No. The spec defines one watch wallet A per task, and target_wallet is a single immutable address. Create one task per wallet.
Is the transfer-snipe config different from the sniper config?
Section titled “Is the transfer-snipe config different from the sniper config?”No. The config object in TransferSnipeCreate and TransferSnipePatch has the same schema as the sniper config, including buy_amount, jito_mode, priority_mode and the sell objects.
Are there transfer-snipe templates?
Section titled “Are there transfer-snipe templates?”The spec defines templates only for sniper and copy-trade. There are no /transfer-snipe/templates endpoints.