Loading...
Loading...
Котировки для ваших приложений и торговое API для ботов: цены, свечи, данные счёта и управление ордерами.
Базовый адрес
https://api.fortexatrade.com
Формат
JSON · UTF-8
Подпись
HMAC-SHA256
Вывод через API
Недоступен
Машинно-читаемое описание (OpenAPI 3.1) — для генераторов клиентов и автоматических клиентов:
https://api.fortexatrade.com/v1/openapi.jsonAPI состоит из двух частей. Котировки открыты без ключа: инструменты, текущие цены и свечи. Торговля требует API-ключ и подпись каждого запроса: баланс счёта, позиции, ордера и управление ими.
BTC/USDT, XAU/USD, EUR/USD. В адресе слэш кодируется как %2F.size — объём позиции в долларах: маржа × плечо. Тот же объём в лотах — lots.GET /v1/market/symbols (contractSize): золото — 100 унций, форекс — 100 000 единиц базовой валюты, нефть — 1000 баррелей, крипта — 1 монета. Маржу под заданный объём считает сервер по цене исполнения — пересчитывать на своей стороне ничего не нужно.Ключи создаются в личном кабинете: Dashboard → API Keys.
| Настройка | Как работает |
|---|---|
| Счёт | Демо или реальный — выбирается один раз при создании. Ключ видит и торгует только на этом счёте; переключатель режима в интерфейсе на него не влияет. |
| Права | Только чтение — счёт, позиции, ордера, история. Чтение и торговля — дополнительно создание, изменение, отмена ордеров и закрытие позиций. |
| Белый список IP | Необязателен: до 20 адресов IPv4/IPv6 или подсетей CIDR. Запросы с других адресов получают ip_not_allowed. Срока действия у ключей нет — ни с белым списком, ни без него. |
| Секрет | Показывается один раз. Сервер хранит его зашифрованным и повторно показать не может — если потерян, удалите ключ и создайте новый. |
| Ограничения | До 10 активных ключей на аккаунт. При блокировке аккаунта все его ключи перестают работать. |
Каждый торговый запрос передаёт четыре заголовка:
| Заголовок | Обязателен | Значение |
|---|---|---|
X-FX-API-KEY | да | Ваш API-ключ |
X-FX-TIMESTAMP | да | Текущее время в миллисекундах (UTC) |
X-FX-RECV-WINDOW | нет | Сколько запрос остаётся действительным, мс. По умолчанию 5000, максимум 60000 |
X-FX-SIGN | да | Подпись HMAC-SHA256 в hex |
X-FX-SIGN = HEX( HMAC_SHA256( secret, timestamp + apiKey + recvWindow + payload ) )payload для GET — строка запроса ровно в том виде, как отправлена, без ? (пустая, если параметров нет).payload для POST — тело JSON ровно в том виде, как отправлено. Подписывайте и отправляйте одну и ту же строку, не сериализуйте объект повторно.recvWindow в подписываемой строке должен совпадать с заголовком X-FX-RECV-WINDOW; если заголовок не передаёте, подписывайте с 5000.GET /v1/time.409 duplicate_request. Для повтора подпишите запрос заново с новой меткой времени и используйте clientOrderId, чтобы ордер не создался дважды.Эталонные значения для проверки своей реализации:
secret your-api-secret
apiKey fx0123456789abcdef0123456789abcd
timestamp 1700000000000
recvWindow 5000
GET /v1/positions?symbol=XAU%2FUSD
payload symbol=XAU%2FUSD
string 1700000000000fx0123456789abcdef0123456789abcd5000symbol=XAU%2FUSD
X-FX-SIGN dc2ab26e240569c88af6ed4d68f790ef44f91a27af07893f362927d9cae8280e
POST /v1/orders
payload {"symbol":"XAU/USD","side":"buy","type":"market","margin":50,"leverage":20}
string 1700000000000fx0123456789abcdef0123456789abcd5000{"symbol":"XAU/USD","side":"buy","type":"market","margin":50,"leverage":20}
X-FX-SIGN 4f274b3465a3019f3342e0998ffaed46ac687549819ec058cfaedc986d7e10fb| Эндпоинты | Лимит | Считается по |
|---|---|---|
| Котировки (/v1/time, /v1/market/*) | 100 запросов в секунду | IP |
| Подписанные GET (счёт, позиции, ордера) | 60 запросов в секунду | API-ключ |
| Подписанные POST (торговля) | 30 запросов в секунду | API-ключ |
При превышении лимита API отвечает 429 rate_limited с заголовком Retry-After: 1.
Ошибки приходят с HTTP-статусом и телом JSON. Логику бота стройте на code — он стабилен; message — для человека и может меняться.
{
"code": "invalid_signature",
"message": "Signature mismatch"
}| HTTP | code | Значение |
|---|---|---|
| 400 | bad_request | Неверные параметры или тело, лишнее поле, битый JSON |
| 400 | invalid_symbol | Инструмент не в формате BASE/QUOTE |
| 400 | invalid_recv_window | X-FX-RECV-WINDOW вне диапазона 1–60000 |
| 400 | leverage_too_high | Плечо выше maxLeverage инструмента |
| 400 | order_rejected | Платформа отклонила ордер: не хватает средств, меньше минимального объёма, рынок закрыт, неверные TP/SL |
| 400 | rejected | Платформа отклонила отмену, изменение, закрытие или установку TP/SL |
| 401 | auth_required | Нет заголовков аутентификации |
| 401 | invalid_api_key | Ключ не найден или удалён |
| 401 | api_key_expired | Истёк срок ключа без белого списка IP |
| 401 | invalid_signature | Подпись не совпадает |
| 401 | timestamp_out_of_window | Метка времени устарела или из будущего |
| 403 | ip_not_allowed | IP запроса не входит в белый список ключа |
| 403 | permission_denied | Ключом только для чтения попытались торговать |
| 403 | account_disabled | Аккаунт заблокирован |
| 404 | symbol_not_found | Инструмент не торгуется |
| 404 | no_quote | Нет актуальной цены по инструменту |
| 404 | order_not_found | На счёте ключа нет такого отложенного ордера |
| 404 | position_not_found | На счёте ключа нет такой открытой позиции |
| 409 | duplicate_request | Этот подписанный запрос уже выполнен |
| 409 | duplicate_client_order_id | Ордер с таким clientOrderId уже создан — в сообщении его orderId |
| 409 | order_in_progress | Ордер с таким clientOrderId ещё обрабатывается |
| 429 | rate_limited | Превышен лимит запросов |
| 500 | internal_error | Внутренняя ошибка |
| 503 | service_unavailable | Сервис платформы временно недоступен — повторите позже |
/v1/timeБез ключаВремя сервера
{
"serverTime": 1789392600000
}/v1/market/symbolsБез ключаТоргуемые инструменты
type: crypto, forex, commodity, index, stock. maxLeverage — максимальное плечо; null, если отдельного ограничения нет.
{
"symbols": [
{
"symbol": "XAU/USD",
"name": "Gold",
"type": "commodity",
"base": "XAU",
"quote": "USD",
"priceDecimals": 2,
"maxLeverage": 100
}
]
}/v1/market/tickerБез ключаТекущая цена инструмента
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
symbol | string | да | XAU/USD |
Цена, по которой рыночный ордер исполнился бы прямо сейчас.
{
"symbol": "XAU/USD",
"price": 4273.97,
"time": 1789392600000
}/v1/market/tickersБез ключаТекущие цены всех инструментов
В ответ попадают только инструменты со свежей ценой.
{
"tickers": [
{ "symbol": "BTC/USDT", "price": 78244.0 },
{ "symbol": "XAU/USD", "price": 4273.97 }
],
"time": 1789392600000
}/v1/market/klinesБез ключаСвечи
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
symbol | string | да | BTC/USDT |
interval | string | нет | 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w. По умолчанию 1h. Месячные (1M) не поддерживаются |
limit | integer | нет | 1–500, по умолчанию 200 |
time — время открытия свечи, свечи идут от старых к новым. Для форекса и металлов volume равен 0.
{
"symbol": "BTC/USDT",
"interval": "1h",
"klines": [
{ "time": 1789390800000, "open": 77698.01, "high": 78247.45, "low": 77481.98, "close": 78244.0, "volume": 512.13907 }
]
}Все эндпоинты ниже требуют подписи и работают только со счётом, к которому привязан ключ. Лишние поля в теле запроса отклоняются с bad_request.
/v1/accountAPI-ключСчёт и баланс
{
"accountType": "demo",
"canTrade": true,
"currency": "USD",
"balance": {
"available": 9850.5,
"locked": 149.5,
"total": 10000.0
}
}/v1/positionsAPI-ключОткрытые позиции
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
symbol | string | нет | Фильтр по инструменту |
{
"positions": [ /* объект позиции */ ]
}Объект позиции:
{
"positionId": 1542,
"symbol": "XAU/USD",
"side": "buy",
"status": "open",
"entryPrice": 4268.4,
"markPrice": 4273.97,
"size": 1000.0,
"lots": 0.0023,
"margin": 50.0,
"leverage": 20,
"liquidationPrice": 4054.98,
"takeProfit": 4300.0,
"stopLoss": 4220.0,
"pnl": 1.3,
"pnlPercent": 2.61,
"fee": 0.7,
"swap": 0.6,
"openedAt": "2026-09-14T13:41:07.512",
"closedAt": null,
"closeReason": null
}/v1/positions/historyAPI-ключЗакрытые и ликвидированные позиции
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
symbol | string | нет | Фильтр по инструменту |
limit | integer | нет | 1–500, по умолчанию 50. Сначала новые |
closeReason: manual, TAKE_PROFIT, STOP_LOSS, ликвидация и другие.
/v1/ordersAPI-ключОтложенные лимитные ордера
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
symbol | string | нет | Фильтр по инструменту |
{
"orderId": 1543,
"symbol": "EUR/USD",
"side": "sell",
"type": "limit",
"status": "new",
"price": 1.162,
"lots": 0.0427,
"margin": 100.0,
"leverage": 50,
"fee": 1.2,
"takeProfit": 1.155,
"stopLoss": null,
"createdAt": "2026-09-14T13:45:00.118"
}/v1/ordersAPI-ключ · торговляСоздать ордер
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
symbol | string | да | XAU/USD |
side | string | да | buy | sell |
type | string | да | market | limit |
lots | number | lots или margin | Объём в лотах, > 0. Сервер сам переводит его в маржу по цене исполнения |
margin | number | lots или margin | Маржа в USD, > 0. Минимум зависит от инструмента |
leverage | integer | да | От 1 до maxLeverage инструмента |
price | number | только limit | Цена ордера. Для market передавать НЕЛЬЗЯ |
takeProfit | number | нет | Цена тейк-профита |
stopLoss | number | нет | Цена стоп-лосса |
clientOrderId | string | нет | Ваш идентификатор, 1–36 символов [A-Za-z0-9_-]. Защищает от дублей 24 часа |
Запрос объёмом в лотах:
{
"symbol": "XAU/USD",
"side": "buy",
"type": "market",
"lots": 0.01,
"leverage": 100,
"clientOrderId": "bot-gold-001"
}Запрос суммой в долларах:
{
"symbol": "EUR/USD",
"side": "sell",
"type": "limit",
"price": 1.162,
"margin": 100,
"leverage": 50,
"takeProfit": 1.155,
"clientOrderId": "grid-eu-017"
}Ответ для лимитного ордера:
{
"orderId": 1543,
"status": "new",
"clientOrderId": "grid-eu-017",
"order": { /* объект ордера */ }
}Ответ для рыночного ордера:
{
"orderId": 1542,
"positionId": 1542,
"status": "filled",
"clientOrderId": null,
"position": { /* объект позиции */ }
}/v1/orders/cancelAPI-ключ · торговляОтменить отложенный ордер
Зарезервированная маржа возвращается на баланс.
// запрос
{ "orderId": 1543 }
// ответ
{ "orderId": 1543, "status": "cancelled" }/v1/orders/amendAPI-ключ · торговляИзменить цену отложенного ордера
Сторона ожидания пересчитывается от рынка на момент изменения.
// запрос
{ "orderId": 1543, "price": 1.165 }
// ответ
{ "order": { /* объект ордера */ } }/v1/positions/closeAPI-ключ · торговляЗакрыть позицию
Позиция закрывается по текущей цене сервера.
// запрос
{ "positionId": 1542 }
// ответ
{ "position": { /* объект позиции, status: closed */ } }/v1/positions/tpslAPI-ключ · торговляУстановить тейк-профит и стоп-лосс
null снимает уровень.// сдвинуть стоп, тейк-профит оставить
{ "positionId": 1542, "stopLoss": 4235 }
// снять тейк-профит
{ "positionId": 1542, "takeProfit": null }Сделка стоит двух вещей: комиссии за круг и платы за перенос через ночь. Обе удерживаются один раз, при закрытии позиции: на счёт возвращается margin + pnl − fee − swap.
Считается при открытии позиции и хранится в её поле fee. Она покрывает и открытие, и закрытие — дважды не берётся. Ставка за лот по каждому инструменту — feePerLotUsd в GET /v1/market/symbols. У отложенного ордера комиссия посчитана сразу, её видно ещё до исполнения.
Позиция, оставшаяся открытой в момент пересчёта суток, платит за перенос. Ставка — процент от объёма позиции за ночь, отдельно для лонга и шорта: swapLongPctPerDay и swapShortPctPerDay в GET /v1/market/symbols.
swapChargeHourUtc (00:00 UTC). Позиция, открытая после него, первый раз платит на следующую ночь.swapTripleWeekday (0 = понедельник) — так оплачивается перенос через выходные.swap позиции и растёт каждую ночь.liquidationPrice у долгой позиции смещается. Читайте его из ответа, а не считайте по плечу.Текущие ставки за ночь, в процентах от объёма (эталонные значения всегда берите из /v1/market/symbols):
| Инструмент | Лонг | Шорт |
|---|---|---|
| Криптовалюта | 0.035% | 0.025% |
| Золото, серебро | 0.020% | 0.012% |
| Нефть | 0.020% | 0.015% |
| Форекс | 0.008% | 0.008% |
Котировки без ключа (cURL):
curl "https://api.fortexatrade.com/v1/market/ticker?symbol=XAU%2FUSD"
curl "https://api.fortexatrade.com/v1/market/klines?symbol=BTC%2FUSDT&interval=1h&limit=100"Клиент на Python с подписью (нужен пакет requests):
import hashlib
import hmac
import json
import time
from urllib.parse import urlencode
import requests
BASE_URL = "https://api.fortexatrade.com"
API_KEY = "fx..." # из кабинета: Dashboard -> API Keys
API_SECRET = "..." # показывается один раз при создании ключа
RECV_WINDOW = "5000"
def _headers(payload: str) -> dict:
timestamp = str(int(time.time() * 1000))
message = timestamp + API_KEY + RECV_WINDOW + payload
signature = hmac.new(API_SECRET.encode(), message.encode(), hashlib.sha256).hexdigest()
return {
"X-FX-API-KEY": API_KEY,
"X-FX-TIMESTAMP": timestamp,
"X-FX-RECV-WINDOW": RECV_WINDOW,
"X-FX-SIGN": signature,
"Content-Type": "application/json",
}
def get(path: str, params: dict | None = None) -> dict:
query = urlencode(params or {})
url = BASE_URL + path + ("?" + query if query else "")
return requests.get(url, headers=_headers(query), timeout=10).json()
def post(path: str, body: dict) -> dict:
# Подписываем и отправляем ОДНУ и ту же строку — без повторной сериализации.
payload = json.dumps(body, separators=(",", ":"))
return requests.post(BASE_URL + path, data=payload, headers=_headers(payload), timeout=10).json()
print(get("/v1/account"))
print(get("/v1/positions", {"symbol": "XAU/USD"}))
# Сначала на демо-ключе!
order = post("/v1/orders", {
"symbol": "XAU/USD",
"side": "buy",
"type": "limit",
"price": 4250,
"margin": 50,
"leverage": 20,
"takeProfit": 4300,
"stopLoss": 4220,
"clientOrderId": "grid-001",
})
print(order)
Клиент на Node.js с подписью:
// Node.js 18+ (встроенные fetch и crypto)
import crypto from "node:crypto";
const BASE_URL = "https://api.fortexatrade.com";
const API_KEY = process.env.FX_API_KEY;
const API_SECRET = process.env.FX_API_SECRET;
const RECV_WINDOW = "5000";
function headers(payload) {
const timestamp = Date.now().toString();
const signature = crypto
.createHmac("sha256", API_SECRET)
.update(timestamp + API_KEY + RECV_WINDOW + payload)
.digest("hex");
return {
"X-FX-API-KEY": API_KEY,
"X-FX-TIMESTAMP": timestamp,
"X-FX-RECV-WINDOW": RECV_WINDOW,
"X-FX-SIGN": signature,
"Content-Type": "application/json",
};
}
export async function get(path, params = {}) {
const query = new URLSearchParams(params).toString();
const url = BASE_URL + path + (query ? `?${query}` : "");
const res = await fetch(url, { headers: headers(query) });
return res.json();
}
export async function post(path, body) {
// Подписываем и отправляем одну и ту же строку.
const payload = JSON.stringify(body);
const res = await fetch(BASE_URL + path, { method: "POST", body: payload, headers: headers(payload) });
return res.json();
}
console.log(await get("/v1/account"));
console.log(await post("/v1/orders/cancel", { orderId: 1543 }));