Safety & Limits¶
The one thing to know¶
An API key created on the settings page can place and close orders.
That is the default. There is no checkbox to turn it off, and nothing on the key-creation screen says so. If you mint a key to let an assistant look up prices, that same key can open a position and close your account's positions.
If that is not what you want, mint a read-only key instead — see below.
Scopes¶
A credential carries scopes. Tools check them.
| Scope | Grants |
|---|---|
read:markets, read:traders, read:whales, read:analytics, read:dashboard |
Market data, news, analytics, dashboards |
read:trade |
Your accounts, positions, orders, limits, milestones, analytics |
trade:execute |
Placing orders, cancelling orders, closing positions |
A key without trade:execute can still tell you everything about your account. It simply cannot act on it. For monitoring, journalling, screening, and briefing — recipes 1 through 5 — that is all you need.
Minting a read-only key¶
The settings page does not offer scope selection, but the API does. Sign in to the terminal, then from the same browser session:
curl -s https://trade.e8markets.com/api/user/api-keys \
-H "Content-Type: application/json" \
-H "Cookie: <your session cookie>" \
-d '{
"name": "read-only monitoring",
"scopes": ["read:markets","read:analytics","read:dashboard","read:trade"]
}'
The response contains the key once. Store it immediately; it is not retrievable afterwards.
Requires copying a session cookie from your browser's developer tools, which is awkward. A scope picker in the settings UI is a known gap. Until it exists, the alternative is OAuth — its consent screen lists every scope being requested, so you at least see
trade:executebefore approving it.
Checking what a key can do¶
curl -s https://trade.e8markets.com/api/mcp \
-H "Authorization: Bearer $E8_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"e8_account_info","arguments":{}}}'
An "Insufficient permissions" error names the scope you are missing. scripts/smoke-test.sh does this check and warns if trade:execute is present.
Rate limits¶
| Credential | Per minute | Per day |
|---|---|---|
| OAuth | 60 | 10,000 |
| API key | Set per key | Set per key |
Exceeding either returns 429 with Retry-After (seconds) and X-RateLimit-* headers. Honour the header — retrying immediately extends the throttle. Budgeting guidance is in Building Your Own Harness.
Kill switches¶
In escalating order. When you are unsure what is running, skip to the last one.
Flatten the account.
Closes every open position at market. Does not stop whatever placed them.
Stop the job.
Stops new work. Leaves existing positions open.
Revoke the credential. Settings → API Keys → Revoke. Or for OAuth, POST /oauth/revoke.
This is the strongest and the fastest. It stops everything using that key immediately, without needing to find the process, log into the server, or know what is running. When something is going wrong and you do not know why, revoke first and diagnose afterwards. A revoked key costs you thirty seconds to replace.
Rules for your agent¶
Put these in your system prompt or skill file. Each one exists because its absence causes a specific failure.
Never state a price the tools did not return. A model that fills a gap with a plausible number produces something that reads exactly like data. If a call fails, the answer is "the call failed" — not an estimate.
Never place an order the user did not authorize in this turn. Not one implied by earlier conversation, not one that follows logically from analysis. Explicit instruction, this turn, or no order.
Size is set in code, never chosen by the model. A hard cap your script enforces cannot be reasoned around. A cap in a prompt can.
No naked entries. Every e8_order_place carries a stopLoss. No exceptions for "just this one".
Report, do not advise. "RSI is 72.4" is a fact. "This is overbought, consider selling" is advice — and an agent comfortable producing it will eventually produce it from a number it invented.
Check isMarketOpen before any order call. Cheaper than handling the rejection.
One account, named explicitly. Hard-code the accountId. A script that cannot see the Live account cannot trade it by accident.
Before you automate execution¶
Recipe 6 in Recipes is the only one that can lose money, and it is built defensively for that reason. Its graduation checklist is not a formality:
- A week read-only, logging what it would have done
- Review that log honestly
- A week on Demo with real orders, checking every fill by hand
- Deliberately trigger the trip wire and confirm it works
- Only then Live, at reduced size
The failure mode that ends funded accounts is not a bad trade. It is a loop that keeps taking bad trades while nobody is watching.
Protecting your credentials¶
- Environment variables or a secret manager. Never in a repo.
- One key per purpose, named for what it does — revoking one then does not break the others.
- Rotate periodically; revoke anything you cannot account for.
- A key in a shell history file or a screenshot is a leaked key. Revoke it.
Back to Terminal Access & MCP, or on to Recipes.