# API reference Все эндпоинты находятся под префиксом `/api/v1`. Swagger UI: `/api/docs`. Защищённые эндпоинты требуют заголовок `Authorization: Bearer `. ## Auth ### `POST /auth/register` Регистрация нового пользователя. **Request:** ```json { "email": "user@example.com", "password": "securePass123", "name": "John" } ``` **Response:** `{ data: { user, accessToken }, meta }` + `Set-Cookie: refresh_token`. ### `POST /auth/login` Вход по email и паролю. **Request:** ```json { "email": "user@example.com", "password": "securePass123" } ``` **Response:** `{ data: { user, accessToken }, meta }` + `Set-Cookie: refresh_token`. ### `POST /auth/refresh` Обновление access token через refresh token из cookie. **Response:** `{ data: { user, accessToken }, meta }` + новый `Set-Cookie: refresh_token`. ### `POST /auth/logout` Выход из системы. Удаляет refresh token из БД и чистит cookie. **Headers:** `Authorization: Bearer ` **Response:** `{ data: { message }, meta }`. ### `GET /auth/me` Информация о текущем пользователе. **Headers:** `Authorization: Bearer ` **Response:** ```json { "data": { "id": 1, "email": "user@example.com", "name": "John", "role": "user" }, "meta": { "fromCache": false, "cachedAt": null } } ``` ### `PATCH /auth/me` Обновление профиля текущего пользователя. **Headers:** `Authorization: Bearer ` **Request:** ```json { "name": "John Doe" } ``` **Response:** `{ data: { id, email, name, role }, meta }`. ## Health ### `GET /health` Проверка состояния сервиса. **Response:** ```json { "status": "ok", "timestamp": "2026-06-13T12:00:00.000Z", "uptime": 1234.56 } ``` ## Securities ### `GET /securities/search` Поиск по инструментам. **Параметры:** | Параметр | Тип | Обязателен | По умолчанию | Описание | |---|---|---|---|---| | `q` | string | да | — | Поисковый запрос (1-100 символов) | | `type` | enum | нет | `all` | Фильтр: `all`, `share`, `bond` | | `limit` | integer | нет | `20` | Лимит результатов | **Response:** ```json { "data": [ { "secid": "SBER", "isin": "RU0009029540", "shortName": "Сбербанк", "type": "share", "listLevel": 1, "currency": "RUB", "price": null } ], "meta": { "fromCache": false, "cachedAt": null } } ``` ### `GET /securities/screener` Скринер ценных бумаг по параметрам цены, объёма, доходности, дюрации, купона и срока погашения. **Параметры:** | Параметр | Тип | Обязателен | Описание | |---|---|---|---| | `type` | enum | да | `share` или `bond` | | `priceMin`, `priceMax` | number | нет | Диапазон цены | | `volumeMin` | number | нет | Минимальный объём | | `yieldMin`, `yieldMax` | number | нет | Диапазон доходности облигаций | | `durationMin`, `durationMax` | number | нет | Диапазон дюрации | | `sortBy` | string | нет | Поле сортировки | | `sortOrder` | enum | нет | `asc` или `desc` | | `page`, `pageSize` | integer | нет | Пагинация | **Response:** `{ data: { items, total, page, pageSize, totalPages }, meta }`. ## Shares ### `GET /securities/shares/:secid` Спецификация акции. **Параметры:** `secid` — тикер (например, `SBER`) **Response:** `ShareResponse` — спецификация + текущие рыночные данные. ```json { "data": { "secid": "SBER", "isin": "RU0009029540", "name": "Сбербанк России ПАО ао", "shortName": "Сбербанк", "latName": null, "listLevel": 1, "issueSize": 21586948000, "faceValue": 3, "faceUnit": "RUB", "type": "common_share", "marketData": { "price": 322.35, "change": 1.15, "changePercent": 0.36, "open": 321.3, "high": 322.66, "low": 321.2, "volume": 1925163, "value": 620184479, "issueCapitalization": 6958336818320, "updatedAt": "2026-06-13T10:30:00.000Z" } }, "meta": { "fromCache": false, "cachedAt": null } } ``` ### `GET /securities/shares/:secid/marketdata` Рыночные данные акции (без спецификации). **Response:** ```json { "data": { "price": 322.35, "change": 1.15, "changePercent": 0.36, "open": 321.3, "high": 322.66, "low": 321.2, "volume": 1925163, "value": 620184479, "issueCapitalization": 6958336818320, "updatedAt": "2026-06-13T10:30:00.000Z" }, "meta": { "fromCache": true, "cachedAt": null } } ``` ### `GET /securities/shares/:secid/dividends` Дивиденды акции. **Параметры:** `secid` — тикер **Response:** ```json { "data": [ { "registryCloseDate": "2026-07-10", "value": 33.4, "currency": "RUB" } ], "meta": { "fromCache": false, "cachedAt": null } } ``` ### `GET /securities/shares/:secid/history` Дневная история торгов акции. **Параметры:** | Параметр | Тип | Обязателен | Описание | |---|---|---|---| | `from` | string (date) | да | Начальная дата (`YYYY-MM-DD`) | | `till` | string (date) | да | Конечная дата (`YYYY-MM-DD`) | **Response:** ```json { "data": [ { "date": "2026-06-13", "open": 321.3, "high": 322.66, "low": 321.2, "close": 322.35, "volume": 1925163, "value": 620184479 } ], "meta": { "fromCache": false, "cachedAt": null } } ``` ## Bonds ### `GET /securities/bonds/:secid` Спецификация облигации. **Параметры:** `secid` — тикер **Response:** `BondResponse` — спецификация + рыночные данные. ```json { "data": { "secid": "SU26238RMFS5", "isin": "RU000A106ZJ4", "name": "ОФЗ 26238", "shortName": "ОФЗ 26238", "latName": null, "listLevel": 1, "issueSize": 500000000, "faceValue": 1000, "faceUnit": "RUB", "matDate": "2041-05-15", "couponValue": 34.9, "couponPercent": 6.98, "couponPeriod": 182, "nextCoupon": "2026-12-01", "accruedInt": 12.45, "bondType": "OFZ", "bondSubType": "", "offerDate": null, "buybackDate": null, "marketData": { "price": 98.45, "yieldToMaturity": 7.12, "duration": 8.34, "accruedInt": 12.45, "couponValue": 34.9, "couponPercent": 6.98, "nextCouponDate": "2026-12-01", "open": 98.3, "high": 98.6, "low": 98.2, "volume": 1500000, "updatedAt": "2026-06-13T10:30:00.000Z" } }, "meta": { "fromCache": false, "cachedAt": null } } ``` ### `GET /securities/bonds/:secid/marketdata` Рыночные данные облигации. ### `GET /securities/bonds/:secid/history` Дневная история торгов облигации. **Параметры:** `from`, `till` (date) **Response:** ```json { "data": [ { "date": "2026-06-13", "closePrice": 98.45, "yieldClose": 7.12, "duration": 8.34 } ], "meta": { "fromCache": false, "cachedAt": null } } ``` ## Candles ### `GET /securities/shares/:secid/candles` Свечи акции. ### `GET /securities/bonds/:secid/candles` Свечи облигации. **Параметры:** | Параметр | Тип | Обязателен | Описание | |---|---|---|---| | `interval` | enum | да | `1h` или `24h` | | `from` | string (date) | да | Начальная дата | | `till` | string (date) | да | Конечная дата | **Response:** ```json { "data": [ { "open": 321.3, "high": 322.66, "low": 321.2, "close": 322.35, "volume": 1925163, "value": 620184479, "begin": "2026-06-13T10:00:00", "end": "2026-06-13T10:59:59" } ], "meta": { "fromCache": false, "cachedAt": null } } ``` ## Портфели Все portfolio endpoints защищены JWT и возвращают envelope `{ data, meta }`. | Endpoint | Method | Описание | |---|---|---| | `/api/v1/portfolios` | GET | Список портфелей пользователя | | `/api/v1/portfolios` | POST | Создать портфель | | `/api/v1/portfolios/:id` | GET | Детали портфеля с позициями и текущими ценами | | `/api/v1/portfolios/:id` | PATCH | Обновить портфель | | `/api/v1/portfolios/:id` | DELETE | Удалить портфель | | `/api/v1/portfolios/:id/positions` | POST | Добавить позицию | | `/api/v1/portfolios/:id/positions/:positionId` | PATCH | Обновить позицию | | `/api/v1/portfolios/:id/positions/:positionId` | DELETE | Удалить позицию | | `/api/v1/portfolios/:id/analytics` | GET | Аналитика портфеля и PnL | `DELETE` endpoints возвращают `{ data: null, meta }`, что отражено в OpenAPI schema и frontend codegen types. ## Broker (T-Bank Invest) Все broker endpoints защищены JWT и возвращают envelope `{ data, meta }`. | Endpoint | Method | Описание | |---|---|---| | `/api/v1/broker/accounts` | GET | Список брокерских счетов и ИИС | | `/api/v1/broker/accounts/:accountId/portfolio` | GET | Портфель счёта: позиции, cash, метаданные | | `/api/v1/broker/accounts/:accountId/events` | GET | События и будущие выплаты (дивиденды, купоны) с фильтром по датам | | `/api/v1/broker/accounts/:accountId/operations` | GET | История операций (cursor pagination) | | `/api/v1/broker/accounts/:accountId/operations/refresh` | POST | Принудительная синхронизация операций из T-Bank | | `/api/v1/broker/accounts/:accountId/positions` | GET | Позиции счёта (с пагинацией) |