API reference
Trade execution
Place an order through your connected broker in two steps: prepare, then execute with a confirmation token.
Two steps
Placing an order takes two calls to the same endpoint, so that nothing is sent to your broker by accident.
- Prepare
Send the order with
"action": "prepare". The API validates it, works out the protective levels and returns aconfirmationToken. No order exists yet. - Execute
Within 5 minutes, send
"action": "execute"with that token. The order goes to your live Alpaca account and the response carries the broker's order.
You need a live key with the trading:execute scope, a Partner plan and an Alpaca account connected to ENTON (see OAuth service).
Prepare or execute a trade
/api/v1/trading/executeTwo calls place one order. The first, with "action": "prepare", validates the order and returns a confirmation token without placing anything. The second, with "action": "execute" and that token, sends the order to your connected broker. Orders always go to the live account.
It also needs:
- A live key. Test keys get 403.
- A Partner plan on the account. Any other plan gets 403.
- A broker connected to your ENTON account (Alpaca, through OAuth).
Known issue
Requests that pass the API-key checks currently fail with 401. This endpoint forwards to an internal route that expects a signed-in session, and the forwarded request does not carry one. The failed call still counts against your rate limit and monthly quota. This page will say so when it is fixed.
Request
JSON body
| Field | Description |
|---|---|
actionstringrequired | Which step this call is.one of "prepare", "execute" |
symbolstring | Prepare only, required. Ticker, for example "AAPL". Upper-cased for you. |
sidestring | Prepare only, required.one of "buy", "sell" |
quantitynumber | Prepare only, required. Shares, more than 0 and at most 10,000.at most 10000 · more than 0 |
orderTypestring | Prepare only.one of "market", "limit" · default "market" |
limitPricenumber | Prepare only. Required when orderType is "limit". |
protectionobject | Prepare only. Stop-loss and take-profit distances as fractions of the entry price. |
protection.stopLossnumber | 0.01 (1%) to 0.50 (50%).default 0.05 · 0.01 to 0.5 |
protection.takeProfitnumber | 0.01 (1%) to 1.00 (100%).default 0.1 · 0.01 to 1 |
confirmationTokenstring | Execute only, required. The token from prepare. It expires 5 minutes after it was issued. |
Response
"action": "prepare"
200 The prepared order and its confirmation token. Nothing has been sent to the broker.
| Field | Description |
|---|---|
actionstring | "prepare".one of "prepare" |
preparedOrderobject | The order as it will be placed. |
preparedOrder.symbolstring | Ticker. |
preparedOrder.sidestring | "buy" or "sell". |
preparedOrder.quantitynumber | Shares. |
preparedOrder.orderTypestring | "market" or "limit". |
preparedOrder.limitPricenumber | Limit price, for limit orders. |
preparedOrder.estimatedCostnumber | Quantity times the reference price. |
preparedOrder.protectionOrdersobject | Protective levels. |
preparedOrder.protectionOrders.stopLossnumber | Stop price. |
preparedOrder.protectionOrders.takeProfitnumber | Take-profit price. |
preparedOrder.protectionOrders.stopLossPercentnumber | The fraction you sent, or 0.05. |
preparedOrder.protectionOrders.takeProfitPercentnumber | The fraction you sent, or 0.10. |
preparedOrder.confirmationTokenstring | Pass this to execute. |
preparedOrder.expiresAtstring | When the token stops working.date-time |
preparedOrder.messagestring | Status text. |
{
"action": "prepare",
"preparedOrder": {
"symbol": "AAPL",
"side": "buy",
"quantity": 10,
"orderType": "market",
"estimatedCost": 1754.3,
"protectionOrders": {
"stopLoss": 166.66,
"takeProfit": 192.97,
"stopLossPercent": 0.05,
"takeProfitPercent": 0.1
},
"confirmationToken": "<confirmation token>",
"expiresAt": "2026-10-23T14:07:11.000Z",
"message": "Order prepared successfully"
}
}"action": "execute"
200 The broker order, as the broker reported it.
| Field | Description |
|---|---|
actionstring | "execute".one of "execute" |
successboolean | Whether the broker accepted the order. |
orderobject | The order. |
order.orderIdstring | The broker's order id. |
order.symbolstring | Ticker. |
order.sidestring | "buy" or "sell". |
order.quantitynumber | Shares ordered. |
order.orderTypestring | Order type. |
order.statusstring | Broker status, for example "accepted" or "filled". |
order.filledPricenumber | Average fill price, once filled. |
order.filledQuantitynumber | Shares filled so far. |
order.submittedAtstring | Submission time. |
order.filledAtstring | Fill time, once filled. |
protectionOrdersobject | Status of the stop-loss and take-profit orders. Each is { "status": "pending" } until the broker reports otherwise. |
messagestring | Status text. |
metadataobject | Request metadata. |
metadata.responseTimeinteger | Milliseconds this request took, measured by the API. |
metadata.environmentstring | Always "live".one of "live" |
{
"action": "execute",
"success": true,
"order": {
"orderId": "<broker order id>",
"symbol": "AAPL",
"side": "buy",
"quantity": 10,
"orderType": "market",
"status": "accepted",
"submittedAt": "2026-10-23T14:03:02.000Z"
},
"protectionOrders": {
"stopLoss": {
"status": "pending"
},
"takeProfit": {
"status": "pending"
}
},
"message": "Order executed successfully",
"metadata": {
"responseTime": 1820,
"environment": "live"
}
}Errors
| Status | When | error |
|---|---|---|
| 403 | The key has neither "trading:execute" nor "*". | Insufficient permissions. Required scope: trading:execute |
| 403 | The key is a test key. | Test API keys cannot execute real trades. Use a live API key for trading. |
| 403 | The account is not on the Partner plan. | Live trading requires a Partner subscription ($99/mo). Upgrade at enton.ai/pricing. |
| 400 | action is missing or another value. | Invalid action. Must be "prepare" or "execute" |
| 400 | Prepare without one of them. | Missing required fields: symbol, side, quantity |
| 400 | side is another value. | Invalid side. Must be "buy" or "sell" |
| 400 | quantity is 0 or less, or over 10,000. | Invalid quantity. Must be between 1 and 10,000 |
| 400 | orderType is another value. | Invalid orderType. Must be "market" or "limit" |
| 400 | orderType is "limit" without limitPrice. | Limit price is required for limit orders |
| 400 | protection.stopLoss is out of range. | Stop loss percentage must be between 0.01 (1%) and 0.50 (50%) |
| 400 | protection.takeProfit is out of range. | Take profit percentage must be between 0.01 (1%) and 1.00 (100%) |
| 400 | Execute without a token. | Missing confirmationToken. First call with action:"prepare" to get a token. |
| 500 | Anything unexpected, including a body that is not valid JSON. | Failed to process trade. Please try again. |
Errors use the standard error body. Any request can also get the authentication errors (401) and the rate-limit error (429).
Examples
Step 1: prepare
curl -X POST "https://enton.ai/api/v1/trading/execute" \
-H "Authorization: Bearer $ENTON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "prepare",
"symbol": "AAPL",
"side": "buy",
"quantity": 10,
"orderType": "market",
"protection": {
"stopLoss": 0.05,
"takeProfit": 0.1
}
}'Step 2: execute
curl -X POST "https://enton.ai/api/v1/trading/execute" \
-H "Authorization: Bearer $ENTON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "execute",
"confirmationToken": "<token from step 1>"
}'Notes
- A confirmation token is signed, expires 5 minutes after prepare, and is accepted only for the account it was issued to.
- Execute places a real order on your live brokerage account. Prepare places nothing.