Toda operación empieza por preparar (prepare): BotRadix valida la acción contra el mercado, tu cuenta y los contratos, la simula y devuelve exactamente lo que hay que firmar o enviar. prepare no ejecuta nada.
El flujo#
POST /orders/preparecon una acción, sus datos y una clave de idempotencia.- Revisa la respuesta:
execution.readydebe sertrue. - Ejecuta según
execution.status:
execution.status | Qué hacer |
|---|---|
signature_ready | Firma execution.typed_data (EIP-712) con la wallet y envíalo al relay. Se usa hoy para abrir y cerrar posiciones |
ready | Firma y envía desde la wallet cada transacción de execution.transactions, en orden |
preflight_failed | No se puede ejecutar ahora. execution.reason explica el motivo (por ejemplo withdraw_margin_insufficient u oracle_unavailable) |
contract_pending | El mercado o el contrato aún no están disponibles para esta acción |
Advertencia
prepare responde HTTP 200 aunque la acción no se pueda ejecutar. Comprueba siempre execution.ready y execution.status antes de firmar nada.
Una acción preparada caduca: 120 segundos las de trading, 180 segundos las de colateral y 300 segundos las intenciones firmadas. Si caduca, vuelve a prepararla.
Camino 1 — Intención firmada (abrir y cerrar posiciones)#
Para open_position, close_position_market y close_position_limit, la respuesta trae un mensaje EIP-712 en lugar de transacciones:
execution.modeessigned_intentyexecution.transactionsestá vacío.- Los datos tipados usan el dominio
BotradixDEX, versión1, chain ID8453, y el router del DEX como contrato verificador. - La wallet lo firma (una firma, no una transacción) y envías la firma al relay:
curl -X POST https://app.botradix.com/api/dex/actions/relay \
-H "Content-Type: application/json" \
-d '{"wallet":"0xTuWallet","intent_id":"dx_…","signature":"0x…"}'
# → {"tx_hash":"0x…","state":"submitted"}El ejecutor de BotRadix envía entonces la transacción. Su coste de red se cobra en USDC de tu colateral del DEX y se muestra antes en execution.costs, así que la wallet no necesita ETH para estas acciones.
Nota
El endpoint de relay forma parte, de momento, de la API web sin versión (/api/dex/actions/relay). Es la forma admitida hoy de enviar intenciones firmadas.
Camino 2 — Transacciones de la wallet#
Para el resto de acciones (colateral, cambios de TP/SL, margen aislado, cancelar y reemplazar), execution.transactions contiene una o varias transacciones:
{ "kind": "action", "from": "0xTuWallet", "to": "0x…", "data": "0x…", "value": "0x0", "deadline": 1790950518 }En los depósitos puede ir primero una de kind: "approval" (aprobación del importe exacto del token). Fírmalas y envíalas en orden desde la misma wallet; necesitan un poco de ETH en Base para el gas.
Depósito de USDC con permit (sin gas). Cuando GET /api/dex/config indica collateral_model.approval.permit: true, añade "permit": true junto a action en un add_collateral de USDC. La respuesta trae entonces execution.mode: "permit_deposit" con typed_data EIP-2612: fírmalo con la wallet y envía {"wallet","intent_id","signature"} a POST /api/dex/actions/relay. Un ejecutor del protocolo envía el depósito y paga el gas. Sin esa marca, o para BAQ, recibes las transacciones de aprobación y depósito.
Si envías tú las transacciones, comunica el hash a POST /api/dex/actions/receipt ({"wallet","intent_id","tx_hash","state"}) para recibir sus webhooks transaction.*; si no, BotRadix solo conoce la operación cuando la indexa desde la cadena.
Camino 3 — Ejecución delegada#
POST /orders/execute envía acciones mediante un ejecutor vinculado a la clave de API (scope trade:execute; orders:manage para cancelar, reemplazar y primitivas de TP/SL). Responde 202 con delegated.command_id, delegated.tx_hash y una status_url; sigue su estado con GET /executions/{command_id}. Envía "prepare_only": true para validar sin enviar.
Acepta, entre otras, open_position, batch (de 1 a 32 acciones), open_market, create_limit, create_stop, increase, reduce, close, cancel, replace, set_tp, clear_tp, set_sl, clear_sl, invert e isolated_manage. Si la clave no tiene un ejecutor vinculado, la API responde 403 delegated_executor_binding_required.
Idempotencia#
/orders/prepare exige una clave de idempotencia, que se toma (en este orden) de la cabecera Idempotency-Key, de payload.idempotency_key o de payload.client_order_id. Debe cumplir ^[A-Za-z0-9._:-]{8,128}$.
- Las claves se asocian a wallet, acción y clave, y se recuerdan 24 horas.
- La misma clave con los mismos datos devuelve la preparación original (
idempotent_replay: true). - La misma clave con datos distintos devuelve
409 IDEMPOTENCY_KEY_CONFLICT; unclient_order_idreutilizado con datos distintos devuelve409 DUPLICATE_CLIENT_ORDER_ID. - La petición se compara con lo que enviaste (
payload, máspermiten los depósitos), en todas las acciones, tambiénopen_position. Los datos se validan antes de buscar la clave, así que un reintento con el mercado desfasado o movido devuelve ese error de validación. Una preparación repetida puede haber caducado: revisaexpires_at_ms.
/orders/execute lee la clave solo de payload.idempotency_key o payload.client_order_id y sigue las mismas reglas: la misma clave con los mismos datos repite la respuesta original, y con datos distintos devuelve 409 IDEMPOTENCY_KEY_CONFLICT.
Datos de open_position#
| Campo | Reglas |
|---|---|
pair_id | id del mercado en /markets |
side | long o short |
order_type | market (por defecto), limit o stop |
margin_mode | cross (por defecto) o isolated |
leverage | Entero desde 1 hasta el máximo del mercado (ver Apalancamiento y margen) |
order_value_usdc | Tamaño de la posición (nocional) en USDC, hasta 6 decimales, dentro del mínimo y máximo del mercado |
reference_price | Obligatorio en órdenes de mercado. Se rechaza con PRICE_DEVIATION_EXCEEDED si se aleja más de un 1,5 % del precio del servidor, o con MARKET_DATA_STALE si los precios tienen más de 8 segundos |
max_slippage_bps | Obligatorio en órdenes de mercado, de 1 a 1000 (del 0,01 % al 10 %) |
limit_price / trigger_price | Obligatorio en órdenes límite / stop |
time_in_force | gtc, ioc o fok; las órdenes de mercado son siempre ioc |
rest_if_unfilled | Solo mercado: deja la parte no ejecutada como orden límite |
post_only | Solo órdenes límite |
take_profit, stop_loss | Opcionales; deben estar en el lado correcto del precio de entrada |
client_order_id | Hasta 96 caracteres; se genera si no se envía |
Ejemplo#
curl -X POST https://app.botradix.com/api/dex/v1/orders/prepare \
-H "X-BotRadix-API-Key: $BOTRADIX_API_KEY" \
-H "Idempotency-Key: mm01-2026-10-02-0001" \
-H "Content-Type: application/json" \
-d '{
"action": "open_position",
"payload": {
"pair_id": 1,
"side": "long",
"order_type": "market",
"margin_mode": "cross",
"order_value_usdc": "100",
"leverage": 5,
"reference_price": "2500.00",
"max_slippage_bps": 50,
"client_order_id": "mm01-2026-10-02-0001"
}
}'La respuesta contiene intent_id, los datos normalizados en payload, execution (estado, datos tipados o transacciones, simulación, costes y plazo) y expires_at_ms.
Después de ejecutar#
GET /transactionslista tus intenciones y su estado en cadena.GET /native/executions/{tx_hash}indica la finalidad:PENDING,PENDING_FINALITY(menos de 8 confirmaciones),REVERTEDoFINAL.- Los webhooks avisan de cambios en órdenes, posiciones, colateral y transacciones.