Appearance
Авторизация и API-ключи
Управление ключами выполняется с пользовательским JWT. Торговые endpoints /api/v1/* принимают только Public API key с префиксом tmpro_api_.
POST /api/auth/login
Выполняет вход по email и password и возвращает JWT. JWT действует 24 часа и используется только для пользовательских endpoints, включая /api/api-keys.
Тело запроса
| Поле | Тип | Обязательное | Ограничения |
|---|---|---|---|
email | string | да | корректный email, до 320 символов |
password | string | да | до 128 символов |
bash
curl --request POST 'https://tradingmonitor.pro/api/auth/login' \
--header 'Content-Type: application/json' \
--data '{
"email": "user@example.com",
"password": "REPLACE_WITH_PASSWORD"
}'csharp
using System.Net.Http.Json;
using System.Text.Json;
using var http = new HttpClient
{
BaseAddress = new Uri("https://tradingmonitor.pro")
};
using var response = await http.PostAsJsonAsync("/api/auth/login", new
{
email = "user@example.com",
password = "REPLACE_WITH_PASSWORD"
});
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{(int)response.StatusCode} {json}");
if (response.IsSuccessStatusCode)
{
using var document = JsonDocument.Parse(json);
var jwt = document.RootElement.GetProperty("token").GetString();
Console.WriteLine($"JWT received: {jwt is not null}");
}python
import requests
response = requests.post(
"https://tradingmonitor.pro/api/auth/login",
json={
"email": "user@example.com",
"password": "REPLACE_WITH_PASSWORD",
},
timeout=30,
)
print(response.status_code, response.text)
jwt = response.json()["token"] if response.ok else NoneУспешный ответ:
json
{
"token": "<user-jwt>",
"sessionToken": "<native-client-session-token>",
"email": "user@example.com"
}Не используйте возвращённый sessionToken в Public REST API.
Основные ошибки:
| HTTP | Code | Причина |
|---|---|---|
401 | invalid_credentials | неверный email или password |
403 | email_not_confirmed | email ещё не подтверждён |
429 | зависит от auth limiter | слишком много попыток входа |
POST /api/api-keys
Создаёт новый Public API key. Endpoint доступен пользователю Business plan при включённом Public API.
Заголовки
http
Authorization: Bearer <user-jwt>
Content-Type: application/jsonТело запроса
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
name | string | да | имя ключа, 1–80 символов |
scopes | string[] | да | непустой массив уникальных поддерживаемых scopes |
expiresAt | ISO 8601 или null | нет | срок действия: в будущем, максимум 365 дней |
Поддерживаемые scopes: signals:write, signals:read, orders:cancel, events:read.
bash
export TMPRO_JWT='REPLACE_WITH_USER_JWT'
curl --request POST 'https://tradingmonitor.pro/api/api-keys' \
--header "Authorization: Bearer $TMPRO_JWT" \
--header 'Content-Type: application/json' \
--data '{
"name": "Production integration",
"scopes": [
"signals:write",
"signals:read",
"orders:cancel",
"events:read"
],
"expiresAt": null
}'csharp
using System.Net.Http.Headers;
using System.Net.Http.Json;
using var http = new HttpClient
{
BaseAddress = new Uri("https://tradingmonitor.pro")
};
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "REPLACE_WITH_USER_JWT");
using var response = await http.PostAsJsonAsync("/api/api-keys", new
{
name = "Production integration",
scopes = new[]
{
"signals:write",
"signals:read",
"orders:cancel",
"events:read"
},
expiresAt = (DateTimeOffset?)null
});
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");python
import requests
jwt = "REPLACE_WITH_USER_JWT"
response = requests.post(
"https://tradingmonitor.pro/api/api-keys",
headers={"Authorization": f"Bearer {jwt}"},
json={
"name": "Production integration",
"scopes": [
"signals:write",
"signals:read",
"orders:cancel",
"events:read",
],
"expiresAt": None,
},
timeout=30,
)
print(response.status_code, response.text)Успешный ответ 201 Created:
json
{
"id": 17,
"name": "Production integration",
"displayPrefix": "tmpro_api_a1b2c3d4...",
"scopes": [
"events:read",
"orders:cancel",
"signals:read",
"signals:write"
],
"createdAt": "2026-07-16T12:00:00Z",
"expiresAt": null,
"lastUsedAt": null,
"revokedAt": null,
"key": "tmpro_api_FULL_SECRET_SHOWN_ONCE"
}Полный secret возвращается только при создании. Ответ содержит:
http
Cache-Control: no-store, max-age=0
Pragma: no-cacheСохраните key в password manager или secret store. Backend хранит только SHA-256 hash.
Лимит ключей
По умолчанию разрешено максимум 5 активных ключей на пользователя.
- revoked-ключи не учитываются;
- истёкшие ключи не учитываются;
- revoked-запись остаётся в базе, но не возвращается
GET /api/api-keys; - истёкший, но не revoked ключ возвращается в списке metadata, хотя использовать его уже нельзя.
Основные ошибки создания:
| HTTP | Code | Причина |
|---|---|---|
400 | invalid_name | неверная длина имени |
400 | invalid_scopes | пустой, неизвестный или дублированный scope |
400 | invalid_expiration | дата не в будущем или дальше 365 дней |
400 | active_key_limit_reached | достигнут лимит активных ключей |
401 | — | JWT отсутствует или недействителен |
403 | business_plan_required | ключи недоступны на текущем плане |
503 | public_api_disabled | создание ключей отключено оператором |
GET /api/api-keys
Возвращает metadata неотозванных ключей текущего пользователя. Secret и hash никогда не возвращаются.
bash
curl 'https://tradingmonitor.pro/api/api-keys' \
--header 'Authorization: Bearer REPLACE_WITH_USER_JWT'csharp
using System.Net.Http.Headers;
using var http = new HttpClient
{
BaseAddress = new Uri("https://tradingmonitor.pro")
};
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "REPLACE_WITH_USER_JWT");
using var response = await http.GetAsync("/api/api-keys");
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");python
import requests
response = requests.get(
"https://tradingmonitor.pro/api/api-keys",
headers={"Authorization": "Bearer REPLACE_WITH_USER_JWT"},
timeout=30,
)
print(response.status_code, response.text)Пример ответа:
json
[
{
"id": 17,
"name": "Production integration",
"displayPrefix": "tmpro_api_a1b2c3d4...",
"scopes": ["events:read", "orders:cancel", "signals:read", "signals:write"],
"createdAt": "2026-07-16T12:00:00Z",
"expiresAt": null,
"lastUsedAt": "2026-07-16T12:10:00Z",
"revokedAt": null
}
]DELETE /api/api-keys/{id}
Немедленно отзывает принадлежащий пользователю API-ключ. Повторный DELETE уже отозванного собственного ключа безопасен, но после revoke ключ исчезает из GET /api/api-keys.
bash
curl --request DELETE 'https://tradingmonitor.pro/api/api-keys/17' \
--header 'Authorization: Bearer REPLACE_WITH_USER_JWT'csharp
using System.Net.Http.Headers;
using var http = new HttpClient
{
BaseAddress = new Uri("https://tradingmonitor.pro")
};
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "REPLACE_WITH_USER_JWT");
using var response = await http.DeleteAsync("/api/api-keys/17");
Console.WriteLine((int)response.StatusCode);python
import requests
response = requests.delete(
"https://tradingmonitor.pro/api/api-keys/17",
headers={"Authorization": "Bearer REPLACE_WITH_USER_JWT"},
timeout=30,
)
print(response.status_code)Ответы:
| HTTP | Значение |
|---|---|
204 No Content | ключ отозван или уже был отозван |
401 Unauthorized | JWT отсутствует или недействителен |
403 business_plan_required | endpoint недоступен на текущем плане |
404 Not Found | ключ отсутствует или принадлежит другому пользователю |