Authentication
Every request carries an OAuth2 access token:
Authorization: Bearer <access_token>
There are two ways to get one:
API key (client_credentials) | Password login | |
|---|---|---|
| Use it for | bots and servers | quick tests, interactive apps |
| Credentials | client_id + client_secret | account ID + password |
| Token scope | API_Trader | Trader (or Investor with the investor password) |
| Your password in the bot? | no | yes |
| Revocable on its own | yes | only by changing the password |
API keys (recommended for bots)
An API key keeps your account password out of your bot. If the key leaks, revoke it without touching your password.
1. Create the key
Log in with your password once, then create a key with that token:
curl -X POST https://api.onlytradeplatform.com/api/v1/accounts/me/client-secret \
-H "Authorization: Bearer $PASSWORD_TOKEN"
{
"success": true,
"code": 201,
"data": {
"client_id": "26100003_4829104756",
"client_secret": "b41c0f…",
"scope": "Trader",
"created_at": 1781251200
}
}
- The
client_secretis shown once — only a hash is stored. Put it in your secret manager or environment, never in source control. - The
client_idlooks like<account_id>_<random digits>— it is not your bare account ID. - The
scopein this response is your account's role. Tokens made from the key get theAPI_Traderscope. - Calling this again replaces the key: the old secret stops working for new logins.
Revoke it any time:
curl -X DELETE https://api.onlytradeplatform.com/api/v1/accounts/me/client-secret \
-H "Authorization: Bearer $PASSWORD_TOKEN"
Replacing or revoking a key stops new logins. A bot that already holds a token keeps working until that session ends. To cut it off immediately, also change your password or log that session out.
2. Exchange the key for a token
curl -X POST "https://api.onlytradeplatform.com/auth/v1/oauth2/token?grant_type=client_credentials&remember_me=true" \
-H "Authorization: Basic $(printf '26100003_4829104756:b41c0f…' | base64)"
The response has the same shape as a password login (below), with
"scope": "API_Trader".
What an API_Trader token can do
| Can | Can't |
|---|---|
| Read the account, journal and money transactions | Change passwords or the investor password |
| Read symbols and price history | Create or revoke API keys |
| Place, modify and cancel orders | Use the in-terminal inbox |
| Modify and close positions | Generate reports (/api/v1/reports) |
| Read deals and export history | |
| Open the WebSocket |
That's everything a trading bot needs. For reports, use a password session.
Password login
POST /auth/v1/oauth2/login?remember_me=true
Authorization: Basic base64(<username>:<password>)
The username can be your numeric account ID, your login alias, or your email (if only one account uses it).
{
"success": true,
"code": 200,
"data": {
"account_id": 26100003,
"access_token": "3d4d16824096e9c0…",
"refresh_token": "9f2b71c55a30e1d4…",
"session_id": "f6a1c2d3-…",
"expires_in": 3600,
"ip_address": "203.0.113.7",
"scope": "Trader"
}
}
| Field | Meaning |
|---|---|
access_token | Send as Authorization: Bearer …. |
refresh_token | Exchange it for new tokens before or after the access token expires. |
session_id | This login's session. The WebSocket needs it. |
expires_in | Access-token lifetime in seconds. |
scope | Trader, Investor (read-only, investor password) or API_Trader. |
Logging in with the investor password gives a read-only Investor session:
it can read everything but every trading call is refused.
Refresh a token
POST /auth/v1/oauth2/refresh/token?remember_me=true
Content-Type: application/json
{ "refresh_token": "9f2b71c55a30e1d4…" }
The response has the same shape as login. Things to know:
- Refresh tokens rotate. You get a new
refresh_tokenevery time and the old one stops working. Always store the latest one — if you refresh with an old one you get401 expired or invalid tokenand must log in again. - The
session_idstays the same, so an open WebSocket stays valid. - Refresh tokens don't expire on a timer. They end when used (rotation), on logout, or when the session is killed.
When to refresh
Refresh when a request returns 401, and proactively before expires_in runs
out. With remember_me=true, the first access token after login can expire
sooner than its expires_in says; it gets the long lifetime from the first
refresh on. The simple rule that always works:
- On any
401, refresh once and retry the request. - If the refresh itself returns
401, get a fresh token with your API key.
The bot example implements exactly this.
Sessions
Every login or key exchange creates a session. Bots need to know three rules:
- Session limit. An account can have up to 5 sessions at once (or just 1, if your broker disabled multi-session for your group). When you go over, the oldest session is killed. So a bot that logs in on every restart can knock your own terminal offline, or be knocked off itself. Reuse tokens and refresh them instead of logging in again.
- Idle logout. A session with no REST call and no open WebSocket for
5 minutes is logged out — unless it was created with
remember_me=true. Bots should always passremember_me=true. - Kicked sessions. When a session is killed (limit reached, broker
disconnected you, trial expired), its WebSocket receives
session_client_logoutand closes about 5 seconds later. Its tokens stop working immediately. Treat it as "log in again", not as "retry".
Log out
DELETE /auth/v1/oauth2/logout
Authorization: Bearer <access_token>
Ends the session, revokes its tokens, and closes its WebSocket. Call it when a bot shuts down cleanly, so it doesn't use up one of your sessions.
Errors
| Status | message | What to do |
|---|---|---|
| 401 | incorrect username or password | Check the credentials. For API keys, the username is the client_id, not the account ID. |
| 401 | missing Authorization header | Send the Authorization header. |
| 401 | expired or invalid token | Refresh; if that fails, log in again. |
| 401 | the account has been deactivated | The account is pending, rejected or disabled — contact your broker. |
| 401 | this trial account has expired | The demo trial ended. |
| 400 | several accounts use this email — sign in with your Account ID | Log in with the numeric account ID. |
| 429 | too many request | More than 60 auth calls a minute from your IP. Back off. |