Docs — Automation
The AlgoThink API
AlgoThink's REST API: authenticate with a bearer key, read suggestions/positions/trades, and optionally approve or close through the same checks as the dashboard.
The AlgoThink API lets your own bot or script read suggestions, positions and trades, and — if you allow it — act on them, without opening the dashboard. It's the same data and the same trade chokepoint the web app uses, just reachable from code.
Authentication
Create a key on Account → Security → Developer API access (requires a Pro plan). The raw key is shown once at creation — store it yourself, AlgoThink only ever keeps a hash of it. Send it as a bearer token on every request:
curl -H "Authorization: Bearer ak_..." \
https://app.algoth.ink/api/v1/suggestions
A key only ever sees and does what your account can — the same tier and entitlements that gate the dashboard gate the API. There's no separate scope system to configure.
Read-only vs. trading keys
Each key is either read-only or allowed to trade, chosen when you
create it. A read-only key can call every GET
endpoint below; a trading key can additionally approve or reject
suggestions and close positions. Keep a read-only key for a
dashboard/monitoring bot and a separate trading key for anything
that places orders — you can revoke one without touching the
other.
Endpoints
| Method | Path | Does |
|---|---|---|
| GET | /api/v1/account | mode, tier, cash and equity |
| GET | /api/v1/suggestions | your pending suggestions |
| GET | /api/v1/positions | your open positions, with live mark/P&L |
| GET | /api/v1/trades | your last 50 closed trades |
| GET | /api/v1/strategies | strategies your plan entitles you to, with health stats |
| POST | /api/v1/suggestions/{id}/approve | execute a suggestion (trading key only) |
| POST | /api/v1/suggestions/{id}/reject | dismiss a suggestion (trading key only) |
| POST | /api/v1/positions/{id}/close | close an open position (trading key only) |
GET /api/v1/account
curl -H "Authorization: Bearer ak_..." \
https://app.algoth.ink/api/v1/account
{
"mode": "paper",
"tier": "pro",
"cash_usdt": 8421.17,
"equity_usdt": 9963.42,
"can_trade": true
}
mode is "paper" or "live";
can_trade reflects this specific key, not your account
as a whole — a read-only key always reports false
here even on a trading-enabled account.
GET /api/v1/suggestions
{
"suggestions": [
{
"id": 4821,
"created_at": 1782300012.4,
"symbol": "BTC/USDT",
"side": "LONG",
"size_usdt": 250.0,
"sl": 61200.0,
"tp": 65400.0,
"strategy": "tsmom_weekly",
"status": "pending"
}
]
}
Only status: "pending" suggestions are returned —
once approved, rejected or expired they drop out of this list (see
/trades for what happened to executed ones).
Timestamps throughout the API are Unix epoch seconds (UTC), not
ISO strings.
GET /api/v1/positions
{
"positions": [
{
"id": 991,
"symbol": "BTC/USDT",
"side": "long",
"qty": 0.0041,
"entry_price": 61850.0,
"sl": 60100.0,
"tp": 64900.0,
"leverage": 2.0,
"strategy": "tsmom_weekly",
"opened_at": 1782212004.1,
"mark": 62430.5,
"value_usdt": 255.97,
"upnl_usdt": 4.75,
"liquidation_price": 31400.2
}
]
}
mark, value_usdt, upnl_usdt
and liquidation_price are computed against the
platform's current price cache at request time, not stored values —
they move between calls. liquidation_price is
null on an unleveraged position.
GET /api/v1/trades
{
"trades": [
{
"id": 883,
"symbol": "ETH/USDT",
"side": "long",
"entry_price": 3120.0,
"close_price": 3244.5,
"opened_at": 1781990004.0,
"closed_at": 1782102004.0,
"close_reason": "tp",
"pnl_usdt": 18.62,
"strategy": "gap_momentum"
}
]
}
Your most recent 50 closed positions, newest first.
close_reason is one of manual,
sl, tp, signal or
liq.
GET /api/v1/strategies
{
"entitled": ["darvas_daily", "gap_momentum", "tsmom_weekly"],
"health": [
{
"strategy": "tsmom_weekly",
"verdict": "FAIL",
"pooled_sharpe": 0.83,
"pct_folds_profitable": 0.58,
"expected_hold_hours": 96.0,
"live_n": 14,
"live_pnl": 62.31,
"live_win_rate": 0.57,
"live_avg_hold_hours": 88.2
}
]
}
entitled is every strategy your plan allows, whether
or not it has traded yet. health has one entry per
strategy with walk-forward and/or live history, and carries a few
more diagnostic fields (exit-reason P&L breakdown, expectancy,
average R-multiple) beyond the ones shown above.
verdict is the strategy's out-of-sample walk-forward
result (PASS/FAIL), independent of how
it's performed on your own account so far.
POST /api/v1/suggestions/{id}/approve
curl -X POST -H "Authorization: Bearer ak_..." \
"https://app.algoth.ink/api/v1/suggestions/4821/approve?leverage=2"
{"ok": true, "msg": "opened LONG 0.004000 BTC/USDT @ 61850.0000 (SL 60100.0000 / TP 64900.0000, 2x)"}
Pass ?leverage=N to override the default leverage,
bounded by your account's own max leverage setting — a value
outside that range fails without touching the suggestion:
{"ok": false, "msg": "leverage must be between 1 and your max 3x"}
Every approve goes through the exact same checks a click in the dashboard would — 2FA, live-trading arming, risk limits — an API key gets no special treatment. A suggestion that's already been approved, rejected or expired fails the same way for both callers:
{"ok": false, "msg": "suggestion is no longer pending"}
POST /api/v1/suggestions/{id}/reject
{"ok": true, "msg": "rejected suggestion #4821"}
POST /api/v1/positions/{id}/close
{"ok": true, "msg": "closed LONG BTC/USDT @ 62430.5000 (manual), pnl +4.75 USDT"}
Closing a position that's already closed, or one that doesn't
belong to your account, fails the same way it would from the
dashboard: {"ok": false, "msg": "position already closed"}.
Status codes
| Code | Meaning | Body |
|---|---|---|
| 200 | request handled — for writes, check ok before assuming it succeeded | {...} or {"ok": bool, "msg": str} |
| 401 | missing, malformed or revoked key | {"detail": "..."} |
| 403 | key valid, but not entitled: below Pro, or a read-only key on a write endpoint | {"detail": "..."} |
| 422 | malformed request — e.g. leverage isn't a number | {"detail": [...]}, FastAPI's standard validation format |
| 429 | rate limit exceeded for this key | {"detail": "..."} |
There's a real distinction worth noting: a write endpoint
almost never returns 4xx for a business-logic failure like
an already-expired suggestion or an over-limit leverage request —
those come back as 200 with {"ok": false,
"msg": "..."}, the same as the dashboard's own buttons would
show you. The 4xx codes above are about the request itself (who you
are, whether you're allowed to ask), not the outcome of the trade
action.
Rate limits
120 requests per minute per key. Cache GET responses
for a few seconds in your own bot rather than polling in a tight
loop — suggestions and positions don't change faster than the
platform's own signal cycle.