Usa una clave API con permisos limitados para una cuenta autorizada. Las órdenes son sintéticas y los pagos elegibles se rigen por el acuerdo.
Ir al quickstartREST / v1curl https://api.tryferm.com/v1/agent/accounts \
-H "Authorization: Bearer $FERM_AGENT_KEY"
https://api.tryferm.comAprobar permite solicitar una cuenta financiada simulada, sujeta a revisión, verificación y acuerdo. No es una cuenta de corretaje.
From any page, abrir tu profile menu y choose API keys. Pick read-only o trading scopes y grant the key exactly the cuentas it may touch.
Point tu bot at our REST API a read state y place órdenes, then reconcile con the ordered event feed. Revoke access anytime.
Six steps desde a fresh cuenta a a bot placing órdenes. Every sample es copy-paste ready en curl, Python, o JavaScript. Pick a language once y the whole page follows.
Agente keys attach a real Ferm cuentas, so tú need at least one cuenta primer. Any cuenta en an evaluación (active), o already financiado (funded / live), puede operar through the API. Tú puede develop tu bot against an evaluación cuenta y let it earn the financiado one.
Log en en the web, abrir tu profile menu (top right) y choose API keys, then Mint a key. Tú va a pick four things:
account:read a read, order:write a operar. Empezar read-only if tú son still testing.The completo key es displayed once. Store it en an environment variable o a secrets manager, never en código o version control. Lost keys cannot be recovered, only replaced.
# The full key is shown exactly once, at creation. Copy it then.
# Anatomy: frm_agent_<key id: 16 hex>_<secret: 64 hex>
export FERM_AGENT_KEY="frm_agent_1a2b3c4d5e6f7a8b_<64-hex-secret>"
List the cuentas tu key fue granted. If this returns tu cuenta, auth, scopes, y grants son all wired up correctly.
curl https://api.tryferm.com/v1/agent/accounts \
-H "Authorization: Bearer $FERM_AGENT_KEY"
{
"status": true,
"data": {
"accounts": [
{
"id": "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10",
"status": "funded",
"balanceCents": 10000000,
"profitShareBps": 9000,
"createdAt": "2026-06-02T15:04:05.000Z"
}
]
}
}
import os, requests
API = "https://api.tryferm.com"
HEADERS = {"Authorization": f"Bearer {os.environ['FERM_AGENT_KEY']}"}
res = requests.get(f"{API}/v1/agent/accounts", headers=HEADERS)
print(res.json())
{
"status": true,
"data": {
"accounts": [
{
"id": "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10",
"status": "funded",
"balanceCents": 10000000,
"profitShareBps": 9000,
"createdAt": "2026-06-02T15:04:05.000Z"
}
]
}
}
const API = "https://api.tryferm.com";
const HEADERS = { Authorization: `Bearer ${process.env.FERM_AGENT_KEY}` };
const res = await fetch(`${API}/v1/agent/accounts`, { headers: HEADERS });
console.log(await res.json());
{
"status": true,
"data": {
"accounts": [
{
"id": "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10",
"status": "funded",
"balanceCents": 10000000,
"profitShareBps": 9000,
"createdAt": "2026-06-02T15:04:05.000Z"
}
]
}
}
10000000 es $100,000.00.401? Check the Authorization header made it through tu HTTP client. Getting an empty list? The key has sin cuenta grants yet.One call returns everything tu strategy needs a make a decision: equity, buying power, abrir posiciones con live mark prices, working límite órdenes, y how far the cuenta es desde each riesgo límite.
export ACCOUNT_ID="1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10"
curl https://api.tryferm.com/v1/agent/accounts/$ACCOUNT_ID/state \
-H "Authorization: Bearer $FERM_AGENT_KEY"
{
"status": true,
"data": {
"tradingState": {
"account": { "id": "1f0c9c7e-…", "status": "funded", "balanceCents": 10000000 },
"currentEquityCents": 10038200,
"buyingPowerCents": 9820000,
"positions": [
{
"id": "6c1d1b2e-4a3f-4f7e-8a9b-2c3d4e5f6a7b",
"symbol": "BTC",
"side": "buy",
"quantity": "0.05",
"entryPrice": 67210.5,
"markPrice": 67480.0,
"unrealizedPnlCents": 1348
}
],
"pendingOrders": [],
"riskThresholds": { "maxDrawdownCents": 800000, "dailyLossCents": 400000 },
"breached": false,
"progress": { "profitBps": 382, "targetBps": 1000 }
}
}
}
ACCOUNT_ID = "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10"
res = requests.get(f"{API}/v1/agent/accounts/{ACCOUNT_ID}/state", headers=HEADERS)
print(res.json())
{
"status": true,
"data": {
"tradingState": {
"account": { "id": "1f0c9c7e-…", "status": "funded", "balanceCents": 10000000 },
"currentEquityCents": 10038200,
"buyingPowerCents": 9820000,
"positions": [
{
"id": "6c1d1b2e-4a3f-4f7e-8a9b-2c3d4e5f6a7b",
"symbol": "BTC",
"side": "buy",
"quantity": "0.05",
"entryPrice": 67210.5,
"markPrice": 67480.0,
"unrealizedPnlCents": 1348
}
],
"pendingOrders": [],
"riskThresholds": { "maxDrawdownCents": 800000, "dailyLossCents": 400000 },
"breached": false,
"progress": { "profitBps": 382, "targetBps": 1000 }
}
}
}
const ACCOUNT_ID = "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10";
const res = await fetch(`${API}/v1/agent/accounts/${ACCOUNT_ID}/state`, { headers: HEADERS });
console.log(await res.json());
{
"status": true,
"data": {
"tradingState": {
"account": { "id": "1f0c9c7e-…", "status": "funded", "balanceCents": 10000000 },
"currentEquityCents": 10038200,
"buyingPowerCents": 9820000,
"positions": [
{
"id": "6c1d1b2e-4a3f-4f7e-8a9b-2c3d4e5f6a7b",
"symbol": "BTC",
"side": "buy",
"quantity": "0.05",
"entryPrice": 67210.5,
"markPrice": 67480.0,
"unrealizedPnlCents": 1348
}
],
"pendingOrders": [],
"riskThresholds": { "maxDrawdownCents": 800000, "dailyLossCents": 400000 },
"breached": false,
"progress": { "profitBps": 382, "targetBps": 1000 }
}
}
}
positions[].id es the id tú use a cerrar a posición o update its brackets; pendingOrders[].id es the id tú use a cancelar a working orden.riskThresholds and progress modalidad the same numbers that score tu evaluación. Use them a tamaño posiciones defensively.Generate a fresh UUID as clientOrderId, then send the orden. If tu connection drops mid-request, retry con the same UUID. Tú va a obtener the original result atrás, never a segundo fill.
curl -X POST https://api.tryferm.com/v1/agent/accounts/$ACCOUNT_ID/orders \
-H "Authorization: Bearer $FERM_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"clientOrderId": "8f2b7c1e-0d4a-4c9b-9a1e-1c2d3e4f5a6b",
"symbol": "BTC",
"side": "buy",
"volume": "0.05",
"orderType": "market",
"takeProfitPercent": 5,
"stopLossPercent": 3
}'
{
"status": true,
"data": {
"order": {
"status": "filled",
"fillPrice": 67480.0,
"position": {
"id": "6c1d1b2e-4a3f-4f7e-8a9b-2c3d4e5f6a7b",
"symbol": "BTC",
"side": "buy",
"quantity": "0.05"
}
}
}
}
import uuid
order = {
"clientOrderId": str(uuid.uuid4()), # retry with the same id - never double-fills
"symbol": "BTC",
"side": "buy",
"volume": "0.05",
"orderType": "market",
"takeProfitPercent": 5,
"stopLossPercent": 3,
}
res = requests.post(f"{API}/v1/agent/accounts/{ACCOUNT_ID}/orders",
headers=HEADERS, json=order)
print(res.json())
{
"status": true,
"data": {
"order": {
"status": "filled",
"fillPrice": 67480.0,
"position": {
"id": "6c1d1b2e-4a3f-4f7e-8a9b-2c3d4e5f6a7b",
"symbol": "BTC",
"side": "buy",
"quantity": "0.05"
}
}
}
}
const order = {
clientOrderId: crypto.randomUUID(), // retry with the same id - never double-fills
symbol: "BTC",
side: "buy",
volume: "0.05",
orderType: "market",
takeProfitPercent: 5,
stopLossPercent: 3,
};
const res = await fetch(`${API}/v1/agent/accounts/${ACCOUNT_ID}/orders`, {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify(order),
});
console.log(await res.json());
{
"status": true,
"data": {
"order": {
"status": "filled",
"fillPrice": 67480.0,
"position": {
"id": "6c1d1b2e-4a3f-4f7e-8a9b-2c3d4e5f6a7b",
"symbol": "BTC",
"side": "buy",
"quantity": "0.05"
}
}
}
}
status: "filled" con the nuevo posición; límite órdenes return status: "pending" con the working orden.Fills, cancels, bracket hits, y breaches all land en an ordered event feed. Persist the last sequence tú processed y poll con sinceSequence. After a crash o disconnect tú replay exactly what tú missed.
# Fetch everything after the last sequence you processed
curl "https://api.tryferm.com/v1/agent/events?accountId=$ACCOUNT_ID&sinceSequence=10431&limit=100" \
-H "Authorization: Bearer $FERM_AGENT_KEY"
{
"status": true,
"data": {
"events": [
{
"eventId": "b1c2d3e4-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
"sequence": 10432,
"type": "order_filled",
"occurredAt": "2026-07-12T08:14:22.101Z",
"accountId": "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10",
"clientOrderId": "8f2b7c1e-0d4a-4c9b-9a1e-1c2d3e4f5a6b",
"data": { }
}
]
}
}
# Fetch everything after the last sequence you processed
params = {"accountId": ACCOUNT_ID, "sinceSequence": 10431, "limit": 100}
res = requests.get(f"{API}/v1/agent/events", headers=HEADERS, params=params)
print(res.json())
{
"status": true,
"data": {
"events": [
{
"eventId": "b1c2d3e4-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
"sequence": 10432,
"type": "order_filled",
"occurredAt": "2026-07-12T08:14:22.101Z",
"accountId": "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10",
"clientOrderId": "8f2b7c1e-0d4a-4c9b-9a1e-1c2d3e4f5a6b",
"data": { }
}
]
}
}
// Fetch everything after the last sequence you processed
const params = new URLSearchParams({
accountId: ACCOUNT_ID,
sinceSequence: "10431",
limit: "100",
});
const res = await fetch(`${API}/v1/agent/events?${params}`, { headers: HEADERS });
console.log(await res.json());
{
"status": true,
"data": {
"events": [
{
"eventId": "b1c2d3e4-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
"sequence": 10432,
"type": "order_filled",
"occurredAt": "2026-07-12T08:14:22.101Z",
"accountId": "1f0c9c7e-8f4b-4c6e-9d2a-7b1e3a5c9d10",
"clientOrderId": "8f2b7c1e-0d4a-4c9b-9a1e-1c2d3e4f5a6b",
"data": { }
}
]
}
}
eventId before acting.One small Python file that proves the whole loop: it finds a granted cuenta, checks it es healthy, places one bracketed orden idempotently, then tails the event feed. Copiar it, export tu key, run it.
#!/usr/bin/env python3
"""Ferm starter bot: reads state, places one bracketed order, tails events.
Run it: export FERM_AGENT_KEY="frm_agent_..." && python3 bot.py
Needs: pip install requests
"""
import os, time, uuid, requests
API = "https://api.tryferm.com"
HEADERS = {"Authorization": f"Bearer {os.environ['FERM_AGENT_KEY']}"}
def get(path, **params):
res = requests.get(f"{API}{path}", headers=HEADERS, params=params, timeout=10)
res.raise_for_status()
return res.json()["data"]
# 1. Find an account this key can trade
account = get("/v1/agent/accounts")["accounts"][0]
account_id = account["id"]
print(f"trading account {account_id} ({account['status']})")
# 2. Look before you leap: never trade a breached account
state = get(f"/v1/agent/accounts/{account_id}/state")["tradingState"]
if state["breached"]:
raise SystemExit("account is breached - read-only until further notice")
print(f"equity ${state['currentEquityCents'] / 100:,.2f}")
# 3. Place one small bracketed market order, idempotently
order = {
"clientOrderId": str(uuid.uuid4()), # reuse on retry: never double-fills
"symbol": "BTC",
"side": "buy",
"volume": "0.01",
"orderType": "market",
"takeProfitPercent": 5,
"stopLossPercent": 3,
}
res = requests.post(f"{API}/v1/agent/accounts/{account_id}/orders",
headers=HEADERS, json=order, timeout=10)
res.raise_for_status()
print("order:", res.json()["data"]["order"]["status"])
# 4. Tail the event feed - real bots persist `since` across restarts
since, seen = 0, set()
while True:
feed = get("/v1/agent/events", accountId=account_id,
sinceSequence=since, limit=100)
for event in feed["events"]:
since = event["sequence"]
if event["eventId"] in seen:
continue # delivery is at-least-once - dedupe by eventId
seen.add(event["eventId"])
print(f"[{event['sequence']}] {event['type']}")
time.sleep(2)
requests. Sin SDK, sin framework. The whole API fits en plain HTTP.sinceSequence somewhere durable so a restart replays exactly the events they missed.Everything above gets tú trading; everything below es what tú come atrás para: exact fields, exact errors, exact límites.
Every request carries a bearer token. Agente endpoints son header-only: they never read tu browser session, so they sit entirely outside cookie y CSRF machinery.
# format: frm_agent_<key id>_<secret>
#
# key id 16 hex chars - identifies the key; visible in your dashboard
# secret 64 hex chars - stored only as a hash; revealed exactly once
frm_agent_1a2b3c4d5e6f7a8b_9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
curl https://api.tryferm.com/v1/agent/accounts \
-H "Authorization: Bearer frm_agent_<keyId>_<secret>"
401 unauthorized; wrong o unknown token → 401 invalid_api_key; revoked → 401 api_key_revoked; expired → 401 api_key_expired.| Scope | Unlocks | Description |
|---|---|---|
account:read | All read endpoints | Read cuenta state, posiciones, operar historial, y the event feed. |
order:write | All trading endpoints | Place y cancelar órdenes, cerrar posiciones, y adjust brackets. |
Keys son default-deny: a key puede only see y operar the cuentas tú explicitly grant it.
404 account_not_found. The API never confirms whether an cuenta exists a a key that cannot access it.Base URL https://api.tryferm.com. All requests y responses son JSON; request bodies son capped at 100 KB; timestamps son ISO 8601 UTC.
| Método | Path & description | Scope |
|---|---|---|
| GET | /v1/agent/accountsList the cuentas this key has been granted. | account:read |
| GET | /v1/agent/accounts/:id/stateLive snapshot: balance, equity, buying power, abrir posiciones, working órdenes, riesgo thresholds, y evaluación progress. | account:read |
| GET | /v1/agent/accounts/:id/tradesPaginated closed-trade historial (límite 1,500, cursor). | account:read |
| GET | /v1/agent/eventsOrdered, replayable event feed (accountId, sinceSequence, límite). | account:read |
| POST | /v1/agent/accounts/:id/ordersColoca una orden de mercado, límite o chase con brackets opcionales de take-profit / stop-loss. | order:write |
| DELETE | /v1/agent/accounts/:id/orders/:orderIdCancelar a working límite orden. :orderId comes desde state.pendingOrders[].id. | order:write |
| POST | /v1/agent/accounts/:id/positions/:tradeId/closeCerrar an abrir posición at mercado. :tradeId comes desde state.posiciones[].id. Optional body { "closePercent": 1,99 } closes only part de the posición. | order:write |
| PATCH | /v1/agent/accounts/:id/positions/:tradeId/bracketsUpdate take-profit / stop-loss en an abrir posición. | order:write |
POST /v1/agente/cuentas/:id/órdenes places a mercado o límite orden. The schema es strict: unknown fields son rechazado rather than ignored.
| Field | Tipo | Obligatorio | Notes |
|---|---|---|---|
clientOrderId | string (UUID) | Obligatorio | Tu idempotency token. Generate a fresh UUID per orden; retries con the same id return the original result instead de filling twice. |
symbol | string | Obligatorio | Instrument symbol, e.g. BTC, EURUSD, US500, XAUUSD. Common aliases (BTCUSD, SPY, GOLD) son normalized automatically. Unknown symbols return 400 unsupported_symbol. |
side | "buy" | "sell" | Obligatorio | Direction de the orden. |
volume | string (decimal) | Obligatorio | Quantity as a decimal string con up a 8 decimal places, e.g. "0.05". Checked against the instrument's min / max / step; out de range returns 400 invalid_order_size. |
orderType | "market" | "limit" | Opcional | Defaults a "mercado". |
limitPrice | string (decimal) | Límite only | Obligatorio when orderType es "límite"; no allowed en mercado órdenes. |
takeProfitPrice | string (decimal) | Opcional | Absolute take-profit precio. Use this o takeProfitPercent, no both. |
takeProfitPercent | integer 1 to 100 | Opcional | Take-profit as a percent distance desde entry. |
stopLossPrice | string (decimal) | Opcional | Absolute stop-loss precio. Use this o stopLossPercent, no both. |
stopLossPercent | integer 1 to 100 | Opcional | Stop-loss as a percent distance desde entry. |
Los instrumentos operables incluyen cripto (BTC, ETH, SOL, …), CFDs 24/7 de índices, materias primas y forex (US50024, XAUUSD24, USOIL24, EURUSD24, …) y CFDs de acciones de EE. UU. (NVDA, TSLA, …). Usa el símbolo exactamente como aparece en la página de mercados.
Before an orden reaches the matching engine it debe clear the same rails as a manual operar: the cuenta debe be en a tradable state (active, funded, o live, otherwise 409 account_not_tradable), have sin retiro en flight (409 trading_withdrawal_pending), y pass sizing, margin, y riesgo checks en the engine itself.
clientOrderId es tu safety net para retries. What happens when the same UUID es sent twice:
| Existente state | Result de the retry |
|---|---|
| Same clientOrderId, posición already abrir | 200: returns the existente posición. Sin segundo fill. |
| Same clientOrderId, límite orden still working | 200: returns the existente pendiente orden. |
| Same clientOrderId, orden already cerrado o cancelled | 400: "client orden id has already been used". Generate a nuevo UUID. |
Cancelar, cerrar, y bracket updates address server-side ids, so read them desde the state endpoint primer. These calls son no idempotent; check state before retrying.
# Cancel a working limit order - id from state.pendingOrders[].id
curl -X DELETE https://api.tryferm.com/v1/agent/accounts/$ACCOUNT_ID/orders/$ORDER_ID \
-H "Authorization: Bearer $FERM_AGENT_KEY"
# Close an open position at market - id from state.positions[].id
# Add -d '{ "closePercent": 50 }' (with Content-Type: application/json) for a partial close
curl -X POST https://api.tryferm.com/v1/agent/accounts/$ACCOUNT_ID/positions/$TRADE_ID/close \
-H "Authorization: Bearer $FERM_AGENT_KEY"
# Move the stop to break-even on an open position
curl -X PATCH https://api.tryferm.com/v1/agent/accounts/$ACCOUNT_ID/positions/$TRADE_ID/brackets \
-H "Authorization: Bearer $FERM_AGENT_KEY" \
-H "Content-Type: application/json" \
-d '{ "stopLossPrice": "67210.50" }'
# Cancel a working limit order - id from state.pendingOrders[].id
requests.delete(f"{API}/v1/agent/accounts/{ACCOUNT_ID}/orders/{order_id}",
headers=HEADERS)
# Close an open position at market - id from state.positions[].id
requests.post(f"{API}/v1/agent/accounts/{ACCOUNT_ID}/positions/{trade_id}/close",
headers=HEADERS)
# Move the stop to break-even on an open position
requests.patch(f"{API}/v1/agent/accounts/{ACCOUNT_ID}/positions/{trade_id}/brackets",
headers=HEADERS, json={"stopLossPrice": "67210.50"})
// Cancel a working limit order - id from state.pendingOrders[].id
await fetch(`${API}/v1/agent/accounts/${ACCOUNT_ID}/orders/${orderId}`, {
method: "DELETE",
headers: HEADERS,
});
// Close an open position at market - id from state.positions[].id
await fetch(`${API}/v1/agent/accounts/${ACCOUNT_ID}/positions/${tradeId}/close`, {
method: "POST",
headers: HEADERS,
});
// Move the stop to break-even on an open position
await fetch(`${API}/v1/agent/accounts/${ACCOUNT_ID}/positions/${tradeId}/brackets`, {
method: "PATCH",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({ stopLossPrice: "67210.50" }),
});
takeProfitPrice / stopLossPrice (decimal strings) o takeProfitPercent / stopLossPercent (integers 1,100). All fields son optional; send only what tú want a change.GET /v1/agente/events es an ordered, replayable log de everything that happens en an cuenta. It es the source de truth tu bot reconciles against.
| Query param | Tipo | Notes |
|---|---|---|
accountId | UUID, obligatorio | The granted cuenta a read events para. |
sinceSequence | integer, default 0 | Returns events con sequence strictly greater than this value. |
limit | 1,500, default 100 | Máximo events per response. |
| Tipo | Fires when |
|---|---|
order_accepted | A límite orden fue accepted y es working. |
order_filled | A mercado orden filled, o a working límite orden executed. |
order_cancelled | A working orden fue cancelled. |
position_closed | An abrir posición fue fully cerrado. |
position_partially_closed | Part de a posición fue cerrado. |
position_brackets_updated | Take-profit / stop-loss en a posición changed. |
account_breached | The cuenta hit a riesgo límite; trading es now blocked. |
evaluation_passed | The evaluación beneficio target fue reached. |
phase_advanced | The cuenta moved a its siguiente phase. |
sequence es monotonic per cuenta. A gap means tú have more a fetch, never that something fue skipped.eventId.clientOrderId, so tú puede match fills a requests exactly.Every response es wrapped en the same envelope, so a single check en estado tells tú whether data o error es present.
{
"status": true,
"data": { }
}
{
"status": false,
"error": {
"code": "insufficient_scope",
"message": "This API key does not have the order:write scope"
}
}
| HTTP | Código | Meaning |
|---|---|---|
| 401 | unauthorized | Sin Authorization header fue sent. |
| 401 | invalid_api_key | Malformed token, unknown key id, o wrong secret. |
| 401 | api_key_revoked | The key fue revoked desde the panel. |
| 401 | api_key_expired | The key es past its expiry date. |
| 403 | insufficient_scope | The key lacks the scope this endpoint requires. |
| 404 | account_not_found | The cuenta does no exist o es no granted a this key. |
| 400 | validation_failed | The body failed validation; error.details lists each bad field. |
| 400 | unsupported_symbol | The symbol es no en the instrument catalog. |
| 400 | invalid_order_size | Volume es outside the instrument's min / max / step. |
| 409 | account_not_tradable | The cuenta es breached, cerrado, o otherwise no en a tradable state. |
| 409 | trading_withdrawal_pending | A pendiente retiro blocks nuevo órdenes until it settles. |
| 429 | rate_limit_exceeded | Too many requests; atrás off y retry. |
| 502 | trading_engine_error | The trading engine returned an unexpected error. Safe a retry reads. |
| 503 | trading_engine_unavailable | The trading engine es unreachable. Retry con backoff. |
Validation failures include an error.details array naming each offending field. Errors surfaced desde inside the trading engine (para example "insufficient buying power") return a human-readable error.message without a machine código.
Límites son generous para polling architectures: a bot reading state once per segundo uses a tenth de its budget.
| Límite | Keyed by | Applies a |
|---|---|---|
| 600 requests / minute | Per API key | All read endpoints |
| 600 requests / minute | Per API key | All orden endpoints |
| 30 failed auths / 10 minutes | Per IP | Requests con bad credentials |
RateLimit-* headers so clients puede pace themselves before hitting 429.429 rate_limit_exceeded, atrás off y retry. Reads son always safe a retry, y órdenes son safe a retry con the same clientOrderId.Automated trading debe never mean handing over the keys a everything. Every control below es en desde the primer request.
Every key es limited a the scopes tú pick (read-only, trading, o both) y only the cuentas tú explicitly grant it.
Kill a key instantly desde the panel. In-flight requests stop the moment it es revoked; sin session lingers.
Agente órdenes run through the identical sizing, account-status, y riesgo checks as the web terminal. Sin shortcuts.
If an cuenta breaches its riesgo límites, trading scopes stop working automatically while reads keep flowing para reconciliation.
Every orden carries a clientOrderId tú generate, so a retried request after a dropped connection never double-fills.
Secrets son shown once at creation y stored only as a hash. Nosotros literally cannot recover a lost key; tú rotate it.
Use de the Agente API es authorized programmatic access under Section 6.2 de the Terms y Conditions. Everything tu keys do es attributed a tu cuenta, y the Acceptable Use Policy y all trading reglas apply exactly as they do a manual trading.
Consigue financiación, genera una clave y quédate hasta el 90% de lo que gane tu estrategia.