Skip to content

Авторизация и API-ключи

Управление ключами выполняется с пользовательским JWT. Торговые endpoints /api/v1/* принимают только Public API key с префиксом tmpro_api_.

POST /api/auth/login

Выполняет вход по email и password и возвращает JWT. JWT действует 24 часа и используется только для пользовательских endpoints, включая /api/api-keys.

Тело запроса

ПолеТипОбязательноеОграничения
emailstringдакорректный email, до 320 символов
passwordstringдадо 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.

Основные ошибки:

HTTPCodeПричина
401invalid_credentialsневерный email или password
403email_not_confirmedemail ещё не подтверждён
429зависит от auth limiterслишком много попыток входа

POST /api/api-keys

Создаёт новый Public API key. Endpoint доступен пользователю Business plan при включённом Public API.

Заголовки

http
Authorization: Bearer <user-jwt>
Content-Type: application/json

Тело запроса

ПолеТипОбязательноеОписание
namestringдаимя ключа, 1–80 символов
scopesstring[]данепустой массив уникальных поддерживаемых scopes
expiresAtISO 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, хотя использовать его уже нельзя.

Основные ошибки создания:

HTTPCodeПричина
400invalid_nameневерная длина имени
400invalid_scopesпустой, неизвестный или дублированный scope
400invalid_expirationдата не в будущем или дальше 365 дней
400active_key_limit_reachedдостигнут лимит активных ключей
401JWT отсутствует или недействителен
403business_plan_requiredключи недоступны на текущем плане
503public_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 UnauthorizedJWT отсутствует или недействителен
403 business_plan_requiredendpoint недоступен на текущем плане
404 Not Foundключ отсутствует или принадлежит другому пользователю

TradingMonitor.Pro documentation.