Build on the Octolit trading platform
One platform, two REST APIs, a WebSocket stream, FIX 4.4, signed webhooks and single sign-on. Provision clients, move money, trade and embed the web trader in your own product.
Everything a broker or partner can integrate
Every capability is a per-brand switch in the Octolit CRM. Switch it on, create a key, start calling.
Partner API
34 operations: provision clients, open accounts, single sign-on both ways, balance posting with idempotency, trading on behalf, MT4 / MT5 links, quotes and chart history.
↗Trading API
22 operations for your clients' own software: symbols, quotes, bars, orders, positions, history. 1 200 requests a minute per key, idempotent orders.
↗WebSocket stream
Live trading quotes and account events over one socket. Ticket-based, 15-minute sessions, batched quotes.
↗FIX 4.4
QUOTE and TRADE sessions over TLS for institutional clients: market data, orders, cancels, replaces, positions.
↗Webhooks
17 signed events (HMAC-SHA256) with 8 retries over 24 hours: clients, logins, trades, margin, money.
↗Single sign-on
Your users land in the trader or dashboard from your own platform with a short RS256 / HS256 JWT, or with a one-time login link.
↗Place an order with one call
Market, limit and stop orders with stop loss, take profit and leverage, checked by the same guards the web trader uses. Every order carries a client_order_id, so a retry can never double-fill.
curl -X POST "https://api.your-brand.com/api/open/v1/orders" \
-H "X-API-Key: $OCTOLIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}'const res = await fetch("https://api.your-brand.com/api/open/v1/orders", {
method: "POST",
headers: {
"X-API-Key": process.env.OCTOLIT_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}),
});
if (!res.ok) throw new Error(`POST failed: ${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);import os, requests
r = requests.request(
"POST",
"https://api.your-brand.com/api/open/v1/orders",
headers={"X-API-Key": os.environ["OCTOLIT_API_KEY"]},
json={
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925,
},
timeout=10,
)
r.raise_for_status()
print(r.json())<?php
$ch = curl_init("https://api.your-brand.com/api/open/v1/orders");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-API-Key: " . getenv("OCTOLIT_API_KEY"),
"Content-Type: " . "application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"client_order_id" => "ord-2026-0001",
"trading_account_id" => 55,
"symbol" => "EURUSD",
"side" => "buy",
"type" => "market",
"lots" => 0.1,
"sl" => 1.0795,
"tp" => 1.0925,
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($data);using var http = new HttpClient();
using var req = new HttpRequestMessage(HttpMethod.Post, "https://api.your-brand.com/api/open/v1/orders");
req.Headers.Add("X-API-Key", Environment.GetEnvironmentVariable("OCTOLIT_API_KEY"));
req.Content = new StringContent("""
{
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}
""", Encoding.UTF8, "application/json");
using var res = await http.SendAsync(req);
res.EnsureSuccessStatusCode();
Console.WriteLine(await res.Content.ReadAsStringAsync());var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://api.your-brand.com/api/open/v1/orders"))
.header("X-API-Key", System.getenv("OCTOLIT_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}
"""))
.build();
var res = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode() + " " + res.body());body := strings.NewReader(`{
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}`)
req, err := http.NewRequest("POST", "https://api.your-brand.com/api/open/v1/orders", body)
if err != nil {
log.Fatal(err)
}
req.Header.Set("X-API-Key", os.Getenv("OCTOLIT_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.StatusCode, string(out))var req = URLRequest(url: URL(string: "https://api.your-brand.com/api/open/v1/orders")!)
req.httpMethod = "POST"
req.setValue(ProcessInfo.processInfo.environment["OCTOLIT_API_KEY"], forHTTPHeaderField: "X-API-Key")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = """
{
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}
""".data(using: .utf8)
let (data, response) = try await URLSession.shared.data(for: req)
print((response as! HTTPURLResponse).statusCode, String(decoding: data, as: UTF8.self))val client = OkHttpClient()
val req = Request.Builder()
.url("https://api.your-brand.com/api/open/v1/orders")
.header("X-API-Key", System.getenv("OCTOLIT_API_KEY"))
.method("POST", """{
"client_order_id": "ord-2026-0001",
"trading_account_id": 55,
"symbol": "EURUSD",
"side": "buy",
"type": "market",
"lots": 0.1,
"sl": 1.0795,
"tp": 1.0925
}""".toRequestBody("application/json".toMediaType()))
.build()
client.newCall(req).execute().use { res ->
println("${res.code} ${res.body?.string()}")
} curl -X PUT "https://api.your-brand.com/api/external/v1/users/cust_10042" \
-H "X-Api-Key: $OCTOLIT_PARTNER_KEY" \
-H "Content-Type: application/json" \
-d '{
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}'const res = await fetch("https://api.your-brand.com/api/external/v1/users/cust_10042", {
method: "PUT",
headers: {
"X-Api-Key": process.env.OCTOLIT_PARTNER_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}),
});
if (!res.ok) throw new Error(`PUT failed: ${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);import os, requests
r = requests.request(
"PUT",
"https://api.your-brand.com/api/external/v1/users/cust_10042",
headers={"X-Api-Key": os.environ["OCTOLIT_PARTNER_KEY"]},
json={
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567",
},
timeout=10,
)
r.raise_for_status()
print(r.json())<?php
$ch = curl_init("https://api.your-brand.com/api/external/v1/users/cust_10042");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Api-Key: " . getenv("OCTOLIT_PARTNER_KEY"),
"Content-Type: " . "application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"brand_id" => 13,
"email" => "anna@example.com",
"first_name" => "Anna",
"last_name" => "Lindqvist",
"country" => "SE",
"phone" => "+46701234567",
]),
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($data);using var http = new HttpClient();
using var req = new HttpRequestMessage(HttpMethod.Put, "https://api.your-brand.com/api/external/v1/users/cust_10042");
req.Headers.Add("X-Api-Key", Environment.GetEnvironmentVariable("OCTOLIT_PARTNER_KEY"));
req.Content = new StringContent("""
{
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}
""", Encoding.UTF8, "application/json");
using var res = await http.SendAsync(req);
res.EnsureSuccessStatusCode();
Console.WriteLine(await res.Content.ReadAsStringAsync());var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://api.your-brand.com/api/external/v1/users/cust_10042"))
.header("X-Api-Key", System.getenv("OCTOLIT_PARTNER_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("""
{
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}
"""))
.build();
var res = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode() + " " + res.body());body := strings.NewReader(`{
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}`)
req, err := http.NewRequest("PUT", "https://api.your-brand.com/api/external/v1/users/cust_10042", body)
if err != nil {
log.Fatal(err)
}
req.Header.Set("X-Api-Key", os.Getenv("OCTOLIT_PARTNER_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.StatusCode, string(out))var req = URLRequest(url: URL(string: "https://api.your-brand.com/api/external/v1/users/cust_10042")!)
req.httpMethod = "PUT"
req.setValue(ProcessInfo.processInfo.environment["OCTOLIT_PARTNER_KEY"], forHTTPHeaderField: "X-Api-Key")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = """
{
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}
""".data(using: .utf8)
let (data, response) = try await URLSession.shared.data(for: req)
print((response as! HTTPURLResponse).statusCode, String(decoding: data, as: UTF8.self))val client = OkHttpClient()
val req = Request.Builder()
.url("https://api.your-brand.com/api/external/v1/users/cust_10042")
.header("X-Api-Key", System.getenv("OCTOLIT_PARTNER_KEY"))
.method("PUT", """{
"brand_id": 13,
"email": "anna@example.com",
"first_name": "Anna",
"last_name": "Lindqvist",
"country": "SE",
"phone": "+46701234567"
}""".toRequestBody("application/json".toMediaType()))
.build()
client.newCall(req).execute().use { res ->
println("${res.code} ${res.body?.string()}")
} Your client ids, our platform
Create clients by your id with PUT /users/{external_id}, open live or demo accounts, book deposits with an idempotency key and send the user straight into the trader with a one-time login link. Nothing to reconcile.
Signed, retried, idempotent
Every delivery carries X-Webhook-Signature: t=…,v1=…, an HMAC-SHA256 of the timestamp and the raw body. Answer 2xx within 10 seconds; otherwise the platform retries at 1 min, 5 min, 30 min, 1 h, 2 h, 6 h and 14 h.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody, header, secret) {
const t = /t=(\d+)/.exec(header)?.[1];
const v1 = /v1=([0-9a-f]+)/.exec(header)?.[1];
if (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const mac = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return timingSafeEqual(Buffer.from(mac), Buffer.from(v1));
}Made for developers
Code in your language
Every endpoint shows the request in cURL, Node, Python, PHP, C#, Java, Go, Swift and Kotlin. Your choice sticks across the site.
Search everything
Press Ctrl K anywhere. Endpoints, fields, error codes and FIX tags are indexed.
Deep links everywhere
Link a colleague straight to one endpoint, one field or one error code.
OpenAPI 3.1 downloads
Generate clients or import into your API tool: both documents are published as YAML and JSON.
Embed the trader
Drop the web trader into your iOS, Android or web app with the embed SDKs and theme it to your brand. SDK guides →
Safe by default
Scoped keys, IP allow-lists, key expiry, replay-proof SSO, idempotent money posting and an audit line for every action done through a key.