مرجع کامل API نسخهٔ v1 برای کلاینتهای Native و اتوماسیون، همراه با endpointهای JSON مرورگر. همهٔ معاملات شبیهسازیشده هستند و هیچ سفارشی نزد کارگزار واقعی اجرا نمیشود.
API برای کلاینتهای Native و اتوماسیون سمت کاربر؛ برای مرورگر از Session استفاده میشود.
https://app.example.com/api/v1
مسیرها در این صفحه مطلق و نسبت به Host هستند.
application/json
درخواست بدنهدار بدون این هدر 415 میگیرد.
simulated
هیچ اتصال یا ارسال سفارش به کارگزار واقعی وجود ندارد.
UTC / ISO 8601
تاریخ فیلترها YYYY-MM-DD است.
API نسخهٔ v1 از Bearer Token استفاده میکند و هیچ Session Cookie نمیسازد.
توکن را از POST /api/v1/auth/login بگیرید و در هدر
Authorization: Bearer <access_token> بفرستید.
totp_code یا recovery_code بررسی میشود.Endpointهای /api/market، /api/candles، /api/crypto/{ref} و /api/chart/* API رسمی Native نیستند و فقط با Session معتبر مرورگر کار میکنند؛ نوشتنها CSRF میخواهند.
{
"success": true,
"data": { "...": "..." },
"meta": {
"request_id": "req_0123456789abcdef"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed.",
"details": { "symbol": "Unknown trading symbol." }
},
"meta": { "request_id": "req_0123456789abcdef" }
}
پاسخها Cache-Control: no-store هستند. برای همبستگی لاگ، هدر X-Request-Id با فرمت معتبر را میتوانید بفرستید؛ در غیر این صورت سرور شناسهٔ تازه میسازد.
| HTTP | Code | معنا |
|---|---|---|
| 400 | INVALID_JSON / IDEMPOTENCY_KEY_REQUIRED | بدنهٔ JSON نامعتبر یا نبود کلید idempotency. |
| 401 | UNAUTHENTICATED / INVALID_TOKEN / TOKEN_EXPIRED / TOKEN_REVOKED | مشکل توکن یا عدم احراز هویت. |
| 403 | TWO_FACTOR_SETUP_REQUIRED / ACCOUNT_SUSPENDED / FORBIDDEN | دسترسی مجاز نیست. |
| 404 | NOT_FOUND | منبع نیست یا به کاربر دیگری تعلق دارد. |
| 409 | CONFLICT / LIMIT_REACHED / ACCOUNT_NOT_ACTIVE | تعارض وضعیت یا قانون معاملاتی. |
| 413 | PAYLOAD_TOO_LARGE | بدنه بیش از ۶۴ کیلوبایت. |
| 415 | UNSUPPORTED_MEDIA_TYPE | Content-Type باید JSON باشد. |
| 422 | VALIDATION_ERROR | ورودی نامعتبر؛ جزئیات در error.details. |
| 429 | RATE_LIMITED / ACCOUNT_LOCKED | محدودیت نرخ یا قفل ورود. |
| 500 | INTERNAL_ERROR | خطای پیشبینینشده؛ جزئیات فقط در لاگ سرور. |
| عملیات | سقف | پنجره |
|---|---|---|
| ورود API | 20 / IP | 900s |
| تازهسازی توکن | 60 / IP | 900s |
| خواندن معاملات و پوزیشن | 180 / user | 60s |
| ثبت/بستن سفارش | 30 / user | 60s |
| ویرایش SL/TP | 60 / user | 60s |
| دادهٔ بازار | 120 / user | 60s |
| اعلانها | 120 / 30 | 60s |
| گزارش عملکرد | 30 / user | 60s |
پاسخ 429 شامل Retry-After و error.details.retry_after است.
page از ۱ و per_page بین ۱ تا ۱۰۰ (پیشفرض ۲۵)؛ نتیجه در meta.pagination.YYYY-MM-DD و مرتبسازی معاملات نزولی بر اساس زمان باز شدن است.+00:00) هستند.entry_slippage / exit_slippage با واحد
points | pips | percent میآید. slippage_effect
اثر خالص ریالی بر P&L است؛ مقدار منفی یعنی هزینه.
null دارند و هیچ مقدار ساختگی برای آنها ساخته نمیشود.
مستندات کامل کانال Realtime در docs/api/websocket.md نگهداری میشود.
این صفحه فقط قرارداد REST را مستند میکند.
دادهٔ Realtime جنبهٔ اطلاعرسانی دارد؛ منبع حقیقت برای موجودی، پوزیشن و P&L همان REST و دیتابیس است.
هیچ ادعای اتصال به فید کارگزار واقعی در این مستندات وجود ندارد.
جستوجو، فیلتر و بازکردن جزئیات هر endpoint. نمونهها با دادههای نمایشی و بدون Secret هستند.
/api/v1/auth/login
ورود و دریافت توکن
Public
ورود با ایمیل و رمز عبور. برای حساب دارای ۲FA، کد TOTP یا کد بازیابی الزامی است. توکن دسترسی کوتاهعمر و توکن تازهسازی چرخشی برمیگردد. این endpoint هیچ Session Cookie ایجاد نمیکند.
| نام | نوع | الزامی | توضیح | محدودیت / پیشفرض |
|---|---|---|---|---|
Content-Type |
string (header) | بله | application/json | — |
X-Client-Version |
string (header) | خیر | نسخهٔ کلاینت، مثلاً 1.4.0 (اختیاری) | — |
User-Agent |
string (header) | خیر | نام و نسخهٔ دستگاه (برای گزارش نشستها) | — |
| نام | نوع | الزامی | توضیح | محدودیت / پیشفرض |
|---|---|---|---|---|
email |
string | بله | ایمیل حساب | حداکثر ۱۹۰ نویسه؛ به حروف کوچک تبدیل میشود. |
password |
string | بله | رمز عبور | حداکثر ۲۰۰ نویسه. |
client_name |
string | خیر | نام نمایشی کلاینت در فهرست نشستها | حداکثر ۶۰ نویسه. |
totp_code |
string | خیر | کد ۶ رقمی TOTP | فقط وقتی ۲FA فعال است. |
recovery_code |
string | خیر | کد بازیابی یکبارمصرف | بهجای TOTP قابل استفاده است. |
{
"email": "trader@example.com",
"password": "Example-Password-123",
"client_name": "android-1.4.0",
"totp_code": "123456"
}
{
"success": true,
"data": {
"token_type": "Bearer",
"access_token": "at_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"expires_in": 900,
"refresh_token": "rt_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"refresh_expires_in": 2592000,
"user": {
"id": 7,
"name": "نمونه کاربر",
"email": "trader@example.com",
"role": "trader",
"status": "active",
"email_verified": true,
"kyc_status": "approved",
"two_factor_enabled": true,
"wallet_balance": "1250.00",
"created_at": "2026-01-12T09:00:00+00:00"
}
},
"meta": {
"execution_mode": "simulated",
"request_id": "req_0123456789abcdef"
}
}
| Status | Code | شرایط |
|---|---|---|
| 422 | VALIDATION_ERROR |
ایمیل/رمز خالی یا بدنهٔ نامعتبر. |
| 401 | INVALID_CREDENTIALS |
ایمیل یا رمز عبور نادرست است. |
| 401 | TWO_FACTOR_REQUIRED |
حساب ۲FA دارد اما کد ارسال نشده است. |
| 401 | INVALID_TWO_FACTOR_CODE |
کد TOTP یا کد بازیابی نادرست/مصرفشده است. |
| 403 | TWO_FACTOR_SETUP_REQUIRED |
مدیر یا کاربر ملزم به ۲FA هنوز ثبتنام نکرده است. |
| 403 | ACCOUNT_SUSPENDED |
حساب تعلیق شده است. |
| 429 | ACCOUNT_LOCKED |
تلاشهای ناموفق ورود بیش از حد مجاز. |
<?php
$base = getenv('AURUM_API_BASE') ?: 'https://app.example.com';
$url = $base . '/api/v1/auth/login';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => <<<'JSON'
{"email":"trader@example.com","password":"Example-Password-123","client_name":"android-1.4.0","totp_code":"123456"}
JSON,
]);
$raw = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($raw === false) {
throw new RuntimeException(curl_error($ch));
}
curl_close($ch);
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
if ($status >= 400 || empty($data['success'])) {
throw new RuntimeException($data['error']['message'] ?? ('HTTP ' . $status));
}
print_r($data['data'] ?? $data);
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import org.json.JSONObject;
public final class AurumApiCall {
public static void call() {
Executors.newSingleThreadExecutor().execute(() -> {
HttpURLConnection connection = null;
try {
URL url = new URL("https://app.example.com/api/v1/auth/login");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(15000);
connection.setReadTimeout(20000);
connection.setDoOutput(true);
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json");
try (OutputStream out = connection.getOutputStream()) {
out.write("{\"email\":\"trader@example.com\",\"password\":\"Example-Password-123\",\"client_name\":\"android-1.4.0\",\"totp_code\":\"123456\"}".getBytes(StandardCharsets.UTF_8));
}
int status = connection.getResponseCode();
InputStream stream = status >= 400 ? connection.getErrorStream() : connection.getInputStream();
String body = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
JSONObject data = new JSONObject(body);
if (status >= 400 || !data.optBoolean("success", false)) {
throw new IOException("HTTP " + status + ": " + body);
}
System.out.println(data.opt("data"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
});
}
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public static class AurumApiCall
{
public static async Task CallAsync()
{
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(20) };
var payload = "{\"email\":\"trader@example.com\",\"password\":\"Example-Password-123\",\"client_name\":\"android-1.4.0\",\"totp_code\":\"123456\"}";
using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://app.example.com/api/v1/auth/login");
request.Headers.Add("Accept", "application/json");
request.Content = new StringContent(payload, Encoding.UTF8, "application/json");
using var response = await http.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {body}");
}
using var doc = JsonDocument.Parse(body);
Console.WriteLine(doc.RootElement.GetProperty("data").GetRawText());
}
}
const baseUrl = process.env.AURUM_API_BASE ?? 'https://app.example.com';
const response = await fetch(`${baseUrl}/api/v1/auth/login`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({"email":"trader@example.com","password":"Example-Password-123","client_name":"android-1.4.0","totp_code":"123456"}),
});
const body = await response.json();
if (!response.ok || body.success !== true) {
throw new Error(body.error?.message ?? `HTTP ${response.status}`);
}
console.log(body.data);
/api/v1/auth/refresh
چرخش توکن تازهسازی
Public
یک توکن تازهسازی معتبر را میسوزاند و جفت توکن جدید برمیگرداند. استفادهٔ دوباره از توکن قدیمی کل خانوادهٔ نشست را باطل میکند.
| نام | نوع | الزامی | توضیح | محدودیت / پیشفرض |
|---|---|---|---|---|
Content-Type |
string (header) | بله | application/json | — |
| نام | نوع | الزامی | توضیح | محدودیت / پیشفرض |
|---|---|---|---|---|
refresh_token |
string | بله | توکن تازهسازی دریافتی از ورود/چرخش قبلی | با پیشوند rt_ و ۶۴ رقم هگز. |
client_name |
string | خیر | در صورت ارسال، نام کلاینت بهروزرسانی میشود | — |
{
"refresh_token": "rt_<your-refresh-token>"
}
{
"success": true,
"data": {
"token_type": "Bearer",
"access_token": "at_fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
"expires_in": 900,
"refresh_token": "rt_fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
"refresh_expires_in": 2592000,
"family_id": "0123456789abcdef0123456789abcdef",
"user": {
"id": 7,
"name": "نمونه کاربر",
"email": "trader@example.com",
"role": "trader",
"status": "active",
"email_verified": true,
"kyc_status": "approved",
"two_factor_enabled": true,
"wallet_balance": "1250.00",
"created_at": "2026-01-12T09:00:00+00:00"
}
},
"meta": {
"request_id": "req_0123456789abcdef"
}
}
| Status | Code | شرایط |
|---|---|---|
| 422 | VALIDATION_ERROR |
refresh_token ارسال نشده است. |
| 401 | INVALID_REFRESH_TOKEN |
توکن ناموجود یا نامعتبر است. |
| 401 | REFRESH_TOKEN_REUSED |
توکن قبلاً مصرف شده؛ خانوادهٔ نشست باطل شد. |
| 401 | REFRESH_TOKEN_EXPIRED |
توکن تازهسازی منقضی شده است. |
| 401 | TOKEN_REVOKED |
رمز عبور پس از صدور توکن تغییر کرده است. |
<?php
$base = getenv('AURUM_API_BASE') ?: 'https://app.example.com';
$url = $base . '/api/v1/auth/refresh';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => <<<'JSON'
{"refresh_token":"rt_<your-refresh-token>"}
JSON,
]);
$raw = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($raw === false) {
throw new RuntimeException(curl_error($ch));
}
curl_close($ch);
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
if ($status >= 400 || empty($data['success'])) {
throw new RuntimeException($data['error']['message'] ?? ('HTTP ' . $status));
}
print_r($data['data'] ?? $data);
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import org.json.JSONObject;
public final class AurumApiCall {
public static void call() {
Executors.newSingleThreadExecutor().execute(() -> {
HttpURLConnection connection = null;
try {
URL url = new URL("https://app.example.com/api/v1/auth/refresh");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(15000);
connection.setReadTimeout(20000);
connection.setDoOutput(true);
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json");
try (OutputStream out = connection.getOutputStream()) {
out.write("{\"refresh_token\":\"rt_<your-refresh-token>\"}".getBytes(StandardCharsets.UTF_8));
}
int status = connection.getResponseCode();
InputStream stream = status >= 400 ? connection.getErrorStream() : connection.getInputStream();
String body = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
JSONObject data = new JSONObject(body);
if (status >= 400 || !data.optBoolean("success", false)) {
throw new IOException("HTTP " + status + ": " + body);
}
System.out.println(data.opt("data"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
});
}
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public static class AurumApiCall
{
public static async Task CallAsync()
{
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(20) };
var payload = "{\"refresh_token\":\"rt_<your-refresh-token>\"}";
using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://app.example.com/api/v1/auth/refresh");
request.Headers.Add("Accept", "application/json");
request.Content = new StringContent(payload, Encoding.UTF8, "application/json");
using var response = await http.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {body}");
}
using var doc = JsonDocument.Parse(body);
Console.WriteLine(doc.RootElement.GetProperty("data").GetRawText());
}
}
const baseUrl = process.env.AURUM_API_BASE ?? 'https://app.example.com';
const response = await fetch(`${baseUrl}/api/v1/auth/refresh`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({"refresh_token":"rt_<your-refresh-token>"}),
});
const body = await response.json();
if (!response.ok || body.success !== true) {
throw new Error(body.error?.message ?? `HTTP ${response.status}`);
}
console.log(body.data);
/api/v1/meta
نسخه و قابلیتهای API
Public
نسخهٔ API، حداقل نسخهٔ کلاینت، قابلیتها و سقفهای عمومی را برمیگرداند. کلاینت میتواند پیش از ورود از ناسازگاری باخبر شود.
{
"success": true,
"data": {
"api_version": "v1",
"min_client_version": "1.0.0",
"latest_client_version": "1.4.0",
"execution_mode": "simulated",
"capabilities": {
"market": true,
"trading": true,
"websocket": true,
"notifications": true,
"reports": true,
"live_broker": false
},
"limits": {
"max_per_page": 100,
"max_candles": 600,
"idempotency_key_header": "Idempotency-Key"
},
"server_time": "2026-10-26T08:05:00+00:00"
},
"meta": {
"request_id": "req_0123456789abcdef"
}
}
<?php
$base = getenv('AURUM_API_BASE') ?: 'https://app.example.com';
$url = $base . '/api/v1/meta';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
],
]);
$raw = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($raw === false) {
throw new RuntimeException(curl_error($ch));
}
curl_close($ch);
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
if ($status >= 400 || empty($data['success'])) {
throw new RuntimeException($data['error']['message'] ?? ('HTTP ' . $status));
}
print_r($data['data'] ?? $data);
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import org.json.JSONObject;
public final class AurumApiCall {
public static void call() {
Executors.newSingleThreadExecutor().execute(() -> {
HttpURLConnection connection = null;
try {
URL url = new URL("https://app.example.com/api/v1/meta");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(15000);
connection.setReadTimeout(20000);
connection.setRequestProperty("Accept", "application/json");
int status = connection.getResponseCode();
InputStream stream = status >= 400 ? connection.getErrorStream() : connection.getInputStream();
String body = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
JSONObject data = new JSONObject(body);
if (status >= 400 || !data.optBoolean("success", false)) {
throw new IOException("HTTP " + status + ": " + body);
}
System.out.println(data.opt("data"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) connection.disconnect();
}
});
}
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public static class AurumApiCall
{
public static async Task CallAsync()
{
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(20) };
using var request = new HttpRequestMessage(new HttpMethod("GET"), "https://app.example.com/api/v1/meta");
request.Headers.Add("Accept", "application/json");
using var response = await http.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {body}");
}
using var doc = JsonDocument.Parse(body);
Console.WriteLine(doc.RootElement.GetProperty("data").GetRawText());
}
}
const baseUrl = process.env.AURUM_API_BASE ?? 'https://app.example.com';
const response = await fetch(`${baseUrl}/api/v1/meta`, {
method: 'GET',
headers: {
Accept: 'application/json',
},
});
const body = await response.json();
if (!response.ok || body.success !== true) {
throw new Error(body.error?.message ?? `HTTP ${response.status}`);
}
console.log(body.data);
Idempotency-Key یکتا استفاده کنید.REFRESH_TOKEN_REUSED کل خانوادهٔ نشست باطل شده است؛ دوباره وارد شوید.
نسخهٔ سند ۱.۰ — 1405/08/04 — فایل مرجع:
docs/API_REFERENCE.md