Signals & Trade Spec
Webhook JSON schema, CEX/DEX venue names, test trading, and D1 ledger columns.
This page
This document details the exact specifications, JSON validation schemas, and internal translation logic that occurs when an external trade signal (such as a TradingView® alert or Email parser) is ingested by the Hoox Gateway and mapped to an active exchange order.
1. Webhook Signal Ingestion Schema
Every signal received by the public gateway at /webhook must contain a valid, authenticated JSON payload. Below is the strict TypeScript interface and parameter schema validated by the gateway's validation middleware:
export interface WebhookSignal {
apiKey: string; // Must match WEBHOOK_API_KEY_BINDING on the hoox gateway
exchange:
| "binance"
| "bybit"
| "mexc"
| "uniswap-ethereum"
| "uniswap-arbitrum"
| "jupiter-solana"; // CEX or DEX venue
action: "LONG" | "SHORT" | "CLOSE_LONG" | "CLOSE_SHORT"; // Position intent
symbol: string; // Asset symbol (e.g. "BTCUSDT", "ETHUSDT")
quantity: number; // Order size (amount of asset or contracts)
leverage?: number; // Optional leverage multiplier (default: 1, max: 125)
idempotencyKey?: string; // Optional unique signature for dedup (auto-generated if omitted)
price?: number; // Optional limit price (default: market price)
/**
* When true, execute on the exchange testnet/sandbox (Binance Futures
* testnet, Bybit testnet). MEXC and DEX venues reject the request.
* Prefer dedicated EXCHANGE_TESTNET_* secrets.
*/
test?: boolean;
}
Parameter Rules & Type Constraints
| Parameter | Type | Required | Constraints |
|---|---|---|---|
apiKey | string | Yes | Must match WEBHOOK_API_KEY_BINDING on the hoox gateway |
exchange | string | Yes | CEX: binance, bybit, mexc. DEX: uniswap-ethereum, uniswap-arbitrum, jupiter-solana |
action | string | Yes | One of: LONG, SHORT, CLOSE_LONG, CLOSE_SHORT |
symbol | string | Yes | CEX: BTCUSDT (dashes/slashes stripped). DEX: BASE/QUOTE required (ETH/USDC) |
quantity | number | Yes | Must be greater than zero; checked against exchange minimum order size |
leverage | number | No | Range: 1 to 125 depending on exchange margin profiles; defaults to 1 (spot) |
idempotencyKey | string | No | If omitted, auto-generated including live/test mode so modes do not dedupe each other |
price | number | No | Limit price; defaults to current market price if omitted |
test | boolean | No | true → testnet for Binance/Bybit; MEXC and DEX venues return TEST_TRADING_UNSUPPORTED |
Test trading
| Exchange | Supports test: true | API host when enabled |
|---|---|---|
| Binance | Yes | testnet.binancefuture.com |
| Bybit | Yes | api-testnet.bybit.com |
| MEXC | No | Rejected (no public REST sandbox) |
| Uniswap Ethereum / Arbitrum | No | Rejected (mainnet-only) |
| Jupiter Solana | No | Rejected (mainnet-only) |
| Side effect | Live | Test (test: true) |
|---|---|---|
| D1 trade status | EXECUTED | TEST_EXECUTED |
| D1 position id | {ex}-{sym}-{side} | {ex}-testnet-{sym}-{side} |
| Telegram label | exchange name | {exchange} [TEST] |
| Analytics exchange blob | bybit | bybit:test |
| WebSocket DO | optional | always REST testnet |
| Agent risk loop | manages OPEN | skips *-testnet-* ids |
| Dashboard stats | counted | excluded from headlines |
Credentials: prefer EXCHANGE_TESTNET_KEY_BINDING / EXCHANGE_TESTNET_SECRET_BINDING. If unset, the live EXCHANGE_* pair is used (warning logged). Deprecated per-venue BINANCE_TESTNET_* / BYBIT_TESTNET_* still resolve as fallbacks.
Full operator guide: Test Trading. DEX spots: DEX spot swaps.
2. Dynamic Payload Translation & Side Mapping
Exchanges do not understand actions like LONG or SHORT. They process order instructions in terms of Side (BUY or SELL) and PositionSide (LONG or SHORT for multi-margin hedge modes).
The trade-worker parses the incoming signal and translates the business logic into exchange-specific API calls:
A. Translation Table (One-Way Margin / Spot)
| Action | Translated Exchange Side | Operation Type |
|---|---|---|
LONG | BUY | Opens a long position |
SHORT | SELL | Opens a short position |
CLOSE_LONG | SELL | Closes an existing long (reduceOnly) |
CLOSE_SHORT | BUY | Closes an existing short (reduceOnly) |
B. Hedge-Mode PositionSide Mapping
When running in hedge mode (supported on Bybit and Binance futures), both LONG and SHORT positions can coexist:
Hedge Mode:
LONG PositionSide = LONG → BUY opens LONG, SELL closes LONG
SHORT PositionSide = SHORT → SELL opens SHORT, BUY closes SHORT
One-Way Mode:
BUY always opens/increases, SELL always closes/reduces
C. Dynamic Position Resolution
When the action is CLOSE, the trade-worker automatically performs a sub-millisecond edge check:
- Queries your local D1 transaction ledger to resolve the active position direction for the symbol.
- If no position is tracked locally, it performs a real-time portfolio balance check against the exchange's private position endpoint.
- Automatically sets the order quantity to match your current open exposure, ensuring a perfect, slippage-free execution that flattens the position without leaving residual micro-contracts.
3. Leverage Scaling & Order Math
If the signal includes a leverage parameter greater than 1 (e.g., "leverage": 10), the trade-worker automatically executes a secure margin transition sequence:
- Set Margin Mode: Configures the symbol's margin structure (Isolated vs. Cross) via the exchange API, matching your manifest defaults.
- Set Leverage Coefficient: Submits a leverage update payload to the exchange prior to routing the order.
- Calculate Collateral: If the order size is defined in USDT terms, the worker scales the execution quantity mathematically: $$\text{Contract Quantity} = \frac{\text{Order Size (USDT)} \times \text{Leverage}}{\text{Current Market Price}}$$
- Precision Rounding: Automatically rounds the calculated quantity down to match the exchange's strict asset decimal precision requirements, preventing API rejects.
Precision Table by Exchange
| Exchange | Price Precision | Quantity Precision | Min Order Size |
|---|---|---|---|
| Binance | Varies by symbol | Varies by symbol | ~$10 equivalent |
| Bybit | 0.1 – 0.001 | 3–6 decimal places | Varies by tier |
| MEXC | 0.1 – 0.00000001 | 2–8 decimal places | ~$5 equivalent |
4. D1 Database Transaction Ledger
Every filled order is persistently written to your globally distributed edge SQLite table. The schema ensures a clean audit log:
CREATE TABLE IF NOT EXISTS trades (
id TEXT PRIMARY KEY,
signal_id TEXT,
timestamp INTEGER NOT NULL,
exchange TEXT NOT NULL, -- binance / bybit / mexc / uniswap-ethereum / …
symbol TEXT NOT NULL,
action TEXT NOT NULL, -- LONG / SHORT / CLOSE_LONG / CLOSE_SHORT
quantity REAL,
price REAL,
leverage INTEGER,
status TEXT NOT NULL, -- EXECUTED / TEST_EXECUTED / FAILED / PENDING
error_message TEXT,
raw_response TEXT,
tenant_id TEXT NOT NULL DEFAULT '',
created_at INTEGER DEFAULT (unixepoch())
);
CREATE TABLE IF NOT EXISTS positions (
id TEXT PRIMARY KEY,
exchange TEXT NOT NULL,
symbol TEXT NOT NULL,
side TEXT NOT NULL, -- LONG or SHORT
entry_price REAL,
mark_price REAL,
liquidation_price REAL,
leverage INTEGER,
size REAL,
unrealized_pnl REAL,
status TEXT NOT NULL, -- OPEN or CLOSED
tenant_id TEXT NOT NULL DEFAULT '',
updated_at INTEGER DEFAULT (unixepoch())
);
You can query the ledger at any time from your local terminal:
# Query the 10 most recent trades in your D1 database
hoox db query "SELECT timestamp, exchange, symbol, action, price, quantity FROM trades ORDER BY timestamp DESC LIMIT 10"
# Check open positions
hoox db query "SELECT symbol, side, size, entry_price FROM positions WHERE status = 'OPEN'"
5. Queue Failover & Guaranteed Delivery
When the exchange API returns an error (timeout, rate limit, HTTP 5xx), the gateway automatically enqueues the trade payload into Cloudflare® Queues for guaranteed delivery:
| Retry Attempt | Delay | Trigger Condition |
|---|---|---|
| 1 | Immediate | First failure |
| 2 | 30 seconds | Network timeout |
| 3 | 1 minute | Rate limit (429) |
| 4 | 5 minutes | Exchange error (502/503) |
| 5 | 15 minutes | Extended maintenance |
| 6 | 30 minutes | Final retry before logging as failed |
After max retries, the trade is logged to D1 with status = 'Failed' — not lost, but visibly flagged for manual review.
Tip
By utilizing time-series logging via Cloudflare® Analytics Engine, Hoox tracks
the exact execution duration of each pipeline step. You can audit the latency
breakdown (e.g., Gateway auth took 1.2ms, Trade-worker signing took 0.8ms,
Bybit API roundtrip took 18.5ms) directly in your Next.js dashboard!
🔗 Next Steps
- Autonomous AI Risk Management — Learn how agent-worker tracks D1 entries to manage trailing stops and drawdowns.
- CLI Reference Manual — Review commands to manage D1 tables, perform dry runs, and tail logs.
- Error Models & Status Codes — Understand all gateway error responses.