Futura Broker API
Read-only REST API to query your account balance and trade history.
The Futura Broker API is a read-only REST API. With an API key you can query your account balance and closed trade history — ideal for spreadsheets, personal dashboards and reports.
API keys are read-only. You cannot open trades, withdraw or transfer through the API. Even so, treat your key like a password: anyone holding the token can read your account's financial data.
Base URL
https://api.futurabroker.com/api/public/v1Authentication
Every request needs the Authorization header with your key as a Bearer token:
Authorization: Bearer fb_live_xxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxGenerate your key directly in the platform, under Settings → Integrations
(futurabroker.com/settings?tab=integrations). The full token is shown
only once at creation time — store it safely. If you lose it, just revoke
the old key and generate another on the same screen. You can keep up to 10
active keys at a time.
Rate limits
- 60 requests per minute per key. When exceeded, the API responds
429with aRetry-Afterheader. - The
X-RateLimit-LimitandX-RateLimit-Remainingheaders accompany every response.
Response format
Every response uses the standard envelope:
{
"success": true,
"data": { },
"meta": { "timestamp": "...", "requestId": "..." }
}On error, success is false and error carries code and message.
Endpoints
GET /ping
Tests connectivity and the validity of your key.
{
"success": true,
"data": {
"pong": true,
"key_prefix": "a6240e5c7b",
"scopes": ["read"],
"server_time": "2026-07-19T06:17:18.476Z"
}
}GET /account/balance
Returns the account balances.
| Field | Type | Description |
|---|---|---|
balance | number | Real balance |
balance_bonus | number | Bonus/affiliate balance |
balance_demo | number | Demo account balance |
currency | string | Currency (e.g. BRL) |
{
"success": true,
"data": {
"balance": 1109.13,
"balance_bonus": 0,
"balance_demo": 25830.67,
"currency": "BRL"
}
}GET /trades
Closed trade history (result win, lose or draw), sorted from newest to
oldest.
Query parameters (all optional):
| Parameter | Type | Description |
|---|---|---|
limit | number | Items per page (1–100, default 50) |
cursor | number | Trade ID for pagination (use next_cursor from the previous response) |
from | ISO 8601 | Start date/time (e.g. 2026-07-01T00:00:00Z) |
to | ISO 8601 | End date/time |
asset | string | Filter by asset (e.g. ETHUSDT) |
result | string | win, lose or draw |
demo | string | true or false |
Fields for each trade:
| Field | Type | Description |
|---|---|---|
id | number | Trade identifier |
asset | string | Traded asset |
direction | string | buy (up) or sell (down) |
amount | number | Invested amount |
entry_price | number | Entry price |
exit_price | number | null | Exit price |
payout_percent | number | Applied payout (%) |
profit | number | null | Profit (positive) or loss (negative) |
result | string | win, lose or draw |
demo | boolean | Whether it was a demo trade |
opened_at | ISO 8601 | Opening time |
closed_at | ISO 8601 | Closing time |
{
"success": true,
"data": {
"trades": [
{
"id": 2703209,
"asset": "ETHUSDT",
"direction": "sell",
"amount": 10,
"entry_price": 1873.59,
"exit_price": 1873.7,
"payout_percent": 80,
"profit": -10,
"result": "lose",
"demo": false,
"opened_at": "2026-06-03T06:40:07.000Z",
"closed_at": "2026-06-03T06:41:00.000Z"
}
],
"next_cursor": 2703206
}
}Pagination: when more results exist, next_cursor holds the ID for the next
page. Repeat the call passing cursor=<next_cursor> until next_cursor returns
null.
Syncing on a schedule? Use from=. Instead of re-paginating your entire
history on every run, store the timestamp of the most recent trade you already
have and fetch only what's new with ?from=<last timestamp>. A typical sync
drops from dozens of requests to one — faster for you, and no risk of
hitting the 60 req/min limit. The example below already does this.
Example: Google Sheets (incremental sync)
Paste the script below into Extensions → Apps Script in your spreadsheet,
replace the token and run syncTrades. The first run imports the full history;
subsequent runs fetch only new trades and append them to the sheet. Add a
trigger (Apps Script → Triggers) to run it periodically.
const API_BASE = 'https://api.futurabroker.com/api/public/v1'
const API_KEY = 'fb_live_xxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
// Fetch with automatic backoff: on rate limit (429), wait for Retry-After and
// retry the SAME page — so a large history syncs fully without breaking, just
// slower.
function fetchWithRetry(url, headers) {
for (let attempt = 0; attempt < 6; attempt++) {
const resp = UrlFetchApp.fetch(url, { headers: headers, muteHttpExceptions: true })
if (resp.getResponseCode() === 429) {
const h = resp.getHeaders()
const wait = Number(h['Retry-After'] || h['retry-after'] || 60)
Utilities.sleep((wait + 1) * 1000)
continue
}
return JSON.parse(resp.getContentText())
}
throw new Error('Persistent rate limit — please try again later')
}
function syncTrades() {
const props = PropertiesService.getScriptProperties()
// Last-sync state: newest trade timestamp + its ID (the ID prevents
// duplicating the trade sitting exactly on the from= boundary).
const lastDate = props.getProperty('last_date')
const lastId = Number(props.getProperty('last_id') || 0)
const headers = { Authorization: 'Bearer ' + API_KEY }
const sheet = SpreadsheetApp.getActiveSheet()
if (sheet.getLastRow() === 0) {
sheet.appendRow(['Date', 'Asset', 'Direction', 'Amount', 'Entry', 'Exit', 'Result', 'Profit'])
}
const fresh = []
let maxId = lastId
let newestDate = lastDate
let cursor = null
do {
let url = API_BASE + '/trades?limit=100'
if (lastDate) url += '&from=' + encodeURIComponent(lastDate)
if (cursor) url += '&cursor=' + cursor
const body = fetchWithRetry(url, headers)
if (!body.success) throw new Error(body.error.message)
body.data.trades.forEach(function (t) {
if (t.id <= lastId) return // already synced in a previous run
fresh.push([
t.closed_at, t.asset, t.direction, t.amount,
t.entry_price, t.exit_price, t.result, t.profit,
])
if (t.id > maxId) maxId = t.id
if (!newestDate || t.opened_at > newestDate) newestDate = t.opened_at
})
cursor = body.data.next_cursor
} while (cursor)
if (fresh.length > 0) {
// Trades arrive newest-first; reverse to keep the sheet chronological.
fresh.reverse()
sheet.getRange(sheet.getLastRow() + 1, 1, fresh.length, fresh[0].length).setValues(fresh)
props.setProperty('last_date', newestDate)
props.setProperty('last_id', String(maxId))
}
}Error codes
| HTTP | code | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or malformed Authorization header |
| 401 | INVALID_API_KEY | Invalid or revoked key |
| 403 | FORBIDDEN_SCOPE | Key lacks the read scope |
| 400 | VALIDATION_ERROR | Invalid query parameter |
| 429 | RATE_LIMITED | Request limit exceeded |