Шаблон ТЗ для проектирования REST API: готовый инструмент для аналитика

от автора

В этой статье — мой рабочий шаблон для описания REST API в ТЗ для разработчиков. В качестве примера я спроектировала учебную базу данных для финтех-системы. Она не привязана к реальному проекту и нужна только для того, чтобы показать, как описывать REST API по шаблону.

Описание исходной базы данных (БД)

В БД четыре таблицы: users (Пользователи), accounts (Счета), currencies (Валюты), transactions (Транзакции). Ниже представлено описание таблиц.

ER-диаграмма БД

ER-диаграмма БД

Таблица users хранит данные о пользователях.

Параметр

Тип

Not null

Значение по умолчанию

Описание

id

int

[v]

Идентификатор

email

varchar(255)

[ ]

Адрес электронной почты

last_name

varchar(255)

[v]

Фамилия

first_name

varchar(255)

[v]

Имя

middle_name

varchar(255)

[v]

Отчество

status

int

[v]

3

Статус: 1 — active, 2 — blocked, 3 — pending, 4 — deleted

is_verified

bool

[v]

false

Флаг подтверждения личности

created_at

timestamp

[v]

Дата и время регистрации

updated_at

timestamp

[ ]

Дата и время последнего обновления

Расшифровка возможных значений параметра users.status:

  • active — пользователь активен. Может входить в систему, совершать операции, создавать транзакции;

  • blocked — пользователь заблокирован. Вход в систему запрещён. Обычно блокируют за нарушение правил, подозрительную активность или по требованию безопасности;

  • pending — пользователь ожидает подтверждения. Например, регистрация завершена, но email не подтверждён, или аккаунт проходит модерацию. Доступ к операциям может быть ограничен;

  • deleted — пользователь удалён или деактивирован. Обычно такой статус используют вместо физического удаления записи, чтобы сохранить историю.

Таблица accounts хранит информацию о банковских счетах пользователей. У одного пользователя может быть несколько счетов, поэтому связь меду таблицами users и accounts — «одна ко многим».

Параметр

Тип

Not Null

Значение по умолчанию

Описание

id

int

[v]

Идентификатор

user_id

int

[v]

Ссылка на пользователя
(владелец счета)

acc_number

varchar(34)

[v]

Номер счета

currency_id

int

[v]

Ссылка на валюту

balance

numeric

[v]

Текущий остаток
(обновляется динамически)

status

int

[v]

1

Статус: 1 — active, 2 — frozen, 3 — closed

is_default

bool

[v]

false

Основной счет

created_at

timestamp

[v]

Дата открытия счета

updated_at

timestamp

[ ]

Дата последнего обновления

Расшифровка возможных значений параметра accounts.status:

  • active — счет активен. Все операции доступны: пополнение, списание, переводы;

  • frozen — счет заморожен. Движение средств приостановлено (обычно по решению банка, суда или службы безопасности). Пополнение может быть доступно, списание — нет;

  • closed — счет закрыт. Операции по счету недоступны. 

Таблица currencies хранит информацию о валютах

Параметр

Тип

Not Null

Значение по умолчанию

Описание

id

int

[v]

Идентификатор

name

varchar(255)

[v]

Наименование

code

varchar(10)

[v]

Код валюты: RUB, USD, EUR

default

bool

[v]

false

Флаг ( 0-обычная валюта, 1-валюта принятая в системе по умолчанию)

user

bool

[v]

false

Флаг ( 0-при расчетах используется курс ЦБ, 1-при расчетах используется пользовательское значение курса)

Таблица transactions хранит информацию о всех движениях средств между счетами.

Параметр

Тип

Not Null

Значение по умолчанию

Описание

id

int

[v]

Идентификатор

type

int

[v]

Тип: 1 — transfer, 2 — payment,
3 — refund

from_account_id

int

[v]

Ссылка на счет списания

to_account_id

int

[v]

Ссылка на счет зачисления

sum

numeric

[v]

Сума транзакции

currency_id

int

[v]

Валюта рубль

Ссылка на валюту

status

int

[v]

1

Статус: 1 — pending, 2 — processing, 3 — completed, 4 — failed, 5 — reversed

description

varchar(255)

[ ]

Описание транзакции

created_at

timestamp

[v]

currencies.created_at

Дата создания

updated_at

timestamp

[v]

Дата последнего обновления

is_recurring

bool

[v]

false

Флаг регулярности платежа

Добавить обязательную проверку: transactions.sum > 0.

Расшифровка возможных значений параметра transactions.type:

  • transfer — перевод средств между собственными счетами пользователя (например, с рублёвого на валютный);

  • payment — платеж в пользу третьего лица или организации (оплата товаров, услуг, коммунальных платежей);

  • refund — возврат средств от продавца или сервиса (частичный или полный).

Расшифровка возможных значений параметра transactions.status:

  • pending — транзакция создана, но ещё не обработана. Ожидает подтверждения или выполнения;

  • processing — транзакция в процессе выполнения;

  • completed — транзакция успешно завершена. Средства списаны со счета отправителя и зачислены на счет получателя;

  • failed — транзакция не выполнена. Средства не были списаны. Причина: недостаточно средств, ошибка валидации, технический сбой;

  • reversed — транзакция отменена (возврат). Средства возвращены на счет отправителя (или частично).

Шаблон описания REST API

Краткое описание модели
Указать URL ресурса
Перечислить разрешенные запросы

Далее перечислить какие параметры содержит модель. Для каждого поля указать тип, обязательность для запросов и маппинг — из какой таблицы подтягивать данные. Если поле ссылается на другую модель или таблицу — это должно быть отражено в ТЗ. Все это можно описать в виде таблицы.

Параметр

Тип

Поле в бд

Обязательность в запросах

Описание

id

int

tablename.id

post, put, delete

Идентификатор

параметр_1

string

tablename.name_1

Параметр для чего-то

параметр_2

bool

tablename.name_2

post

Обязательный параметр

  1. Если параметр вычисляемый, добавить алгоритм расчета

  2. Описать бизнес-правила, которые должны выполняться при обработке запроса (при наличии). Например, некоторые параметры становятся обязательными или необязательными в зависимости от того, что указано в другом поле.

  3. Указать все ограничения (например, параметр_1 > 0, значение параметра_1 не может быть отрицательным)

  4. Описать проверки, которые должны выполняться перед выполнением операции

  5. Добавить примеры запросов и ответов

  6. Описать обработку всех невалидных данных (ошибки валидации)

  7. Описать обработку ошибок на уровне бизнес-логики

Пример описания REST API на учебной БД согласно шаблону

Создать модель currencies

Модель currencies предназначена для получения данных о валютах.
URL: https://XXXXX/api/v1/currencies.json
Разрешенные запросы: только GET, у пользователя не должно быть возможности добавлять и менять валюту через API

Параметр

Тип

Поле в бд

Обязательность в запросах

Описание

id

int

currencies.id

post, put, delete

Идентификатор

name

string

currencies.name

Наименование

code

string

currencies.code

post

Код валюты: RUB, USD, EUR

default

bool

currencies.default

post

Флаг ( 0-обычная валюта, 1-валюта принятая в системе по умолчанию)

user

bool

currencies.user

post

Флаг ( 0-при расчетах используется курс ЦБ, 1-при расчетах используется пользовательское значение курса)

Пример: получить список валют, GET-запрос

GET /api/v1/currencies

Пример ответа на GET-запрос

{  "data": [    {      "id": 1,      "name": "Российский рубль",      "code": "RUB",      "default": true,      "user": false    },    {      "id": 2,      "name": "Доллар США",      "code": "USD",      "default": false,      "user": false    },    {      "id": 3,      "name": "Евро",      "code": "EUR",      "default": false,      "user": true    }  ]}

Создать модель users

Модель users описывает пользователя системы. Содержит персональные данные, статус и временные метки.
https://XXXXX/api/v1/users.json
Разрешенные запросы: GET, POST, PUT, DELETE

Параметр

Тип

Поле в бд

Обязательность в запросах

Описание

id

int

users.id

post, put, delete

Идентификатор

email

string

users.email

Адрес электронной почты

last_name

string

users.last_name

post

Фамилия

first_name

string

users.first_name

post

Имя

middle_name

string

users.middle_name

post

Отчество

status

int

users.status

Статус: 1 — active, 2 — blocked, 3 — pending, 4 — deleted
(по умолчанию — pending)

is_verified

bool

users.is_verified

Флаг подтверждения личности
(по умолчанию false)

created_at

datetime

users.created_at

Дата и время регистрации

updated_at

datetime

users.updated_at

Дата и время последнего обновления

Пример корректного POST-запроса

POST /api/v1/users HTTP/1.1Host: your-api-domain.comContent-Type: application/json{  "last_name": "Сидоров",  "first_name": "Алексей",  "middle_name": "Петрович"}

Пример ответа на POST-запрос (201 Created)

{  "data": {    "id": 3,    "email": null,    "last_name": "Сидоров",    "first_name": "Алексей",    "middle_name": "Петрович",    "status": 3,    "is_verified": false,    "created_at": "2025-06-30T16:00:00Z",    "updated_at": null  }}

В ответе на POST- и PUT-запросы можно возвращать только id.

1 Если в запросе не указан хотя бы один из обязательных параметров, то при попытке отправить запрос выводить ошибку: «Отсутствует обязательный параметр — наименование параметра«.

Пример некорректного POST-запроса

POST /api/v1/users HTTP/1.1Host: your-api-domain.comContent-Type: application/json{  "first_name": "Иван",  "middle_name": "Иванович"}

Пример ответа (400 Bad Request)

{  "error": "Отсутствует обязательный параметр - last_name"}

2 Если в запросе указано некорректное значение параметра status, то выводить ошибку: «Некорректное значение параметра status. Допустимые значения: 1 (active), 2 (blocked), 3 (pending), 4 (deleted)»

Пример некорректного POST-запроса

POST /api/v1/users HTTP/1.1Host: your-api-domain.comContent-Type: application/json{  "last_name": "Иванов",  "first_name": "Иван",  "middle_name": "Иванович",  "status": 5}

Пример ответа (400 Bad Request)

{  "error": "Некорректное значение status. Допустимые значения: 1 (active), 2 (blocked), 3 (pending), 4 (deleted)"}

Если в post-запросе не задан параметр status, то автоматически присваивать значение pending.

Создать модель accounts

Модель accounts описывает банковские счета пользователей. У одного пользователя может быть несколько счетов.
https://XXXXX/api/v1/accounts.json
Разрешенные запросы: GET, POST, PUT, DELETE

Параметр

Тип

Поле в бд

Обязательность в запросах

Описание

id

int

accounts.id

Идентификатор

user_id

int

accounts.user_id

post

Ссылка на пользователя
(владелец счета)

acc_number

string

accounts.acc_number

post

Номер счета

currency_id

int

accounts.currency_id

post

Ссылка на валюту

balance

float

accounts.balance

Текущий остаток
(обновляется динамически)

status

int

accounts.status

Статус: 1 — active, 2 — frozen, 3 — closed

is_default

bool

accounts.is_default

Основной счет

created_at

datetime

accounts.created_at

Дата открытия счета

updated_at

datetime

accounts.updated_at

Дата последнего обновления

1 Если в запросе не указан хотя бы один из обязательных параметров, то при попытке отправить запрос выводить ошибку: «Отсутствует обязательный параметр — наименование параметра«.

Пример некорректного POST-запроса

POST /api/v1/accounts HTTP/1.1Host: your-api-domain.comContent-Type: application/json{  "acc_number": "40817810099910004314",  "currency_id": 1,  "is_default": false}

Пример ответа (400 Bad Request)

{  "error": "Отсутствует обязательный параметр - user_id"}

2 Если в запросе указана некорректная ссылка (идентификатор) для параметров user_id и currency_id или некорректный номер счета (acc_number) или статус (status), выводить ошибку «Некорректное значение параметра наименование_параметра«

3 Поле balance является вычисляемым. Оно не передаётся в запросах и не хранится как статическое значение. Баланс рассчитывается как разница между всеми успешными поступлениями и списаниями по счёту. Обновление происходит автоматически при изменении статуса транзакции на completed или reversed.

  • Поле balance не может быть установлено клиентом.

  • Баланс рассчитывается как сумма всех успешных (status=3) транзакций:

    balance = sum(completed incoming) - sum(completed outgoing)

  • Обновление баланса происходит автоматически при изменении статуса транзакции на completed или reversed.

Расшифровка

Откуда брать

Что брать

completed incoming

таблица transactions

Все записи, где to_account_id = ID счёта и status = 3 (completed)

completed outgoing

таблица transactions

Все записи, где from_account_id = ID счёта и status = 3 (completed)

Как выглядит в SQL:

-- Остаток по счёту на текущий моментSELECT COALESCE(SUM(    CASE         WHEN to_account_id = {account_id} THEN sum        WHEN from_account_id = {account_id} THEN -sum        ELSE 0    END), 0) AS balanceFROM transactionsWHERE (to_account_id = {account_id} OR from_account_id = {account_id})  AND status = 3;

В API параметр balance рассчитывается:

balance = SUM(transactions.sum WHERE to_account_id = accounts.id AND status = 3) - SUM(transactions.sum WHERE from_account_id = accounts.id AND status = 3)

При попытке вручную задать значение параметра balance в POST- или PUT-запросах есть два сценария поведения API:

  1. Запрос отправляется успешно, но входное значение параметра balance игнорируется и считается автоматически по формуле, соответственно в бд записывается вычисленное значение

  2. Вывести в ответе ошибку (400 Bad Request):

{  "error": "Поле balance не может быть задано клиентом. Значение рассчитывается автоматически."}

Создать модель transactions

Модель transactions описывает движение средств между счетами пользователей.
https://XXXXX/api/v1/transactions.json
Разрешенные запросы: GET, POST, PUT, DELETE

Параметр

Тип

Поле в бд

Обязательность в запросах

Описание

id

int

transactions.id

Идентификатор

type

int

transactions.type

post

Тип: 1 — transfer, 2 — payment,
3 — refund

from_account_id

int

transactions.from_account_id

post

Ссылка на счет списания

to_account_id

int

transactions.to_account_id

post

Ссылка на счет зачисления

sum

float

transactions.sum

post

Сумма транзакции

currency_id

int

transactions.currency_id

Ссылка на валюту

status

int

transactions.status

Статус: 1 — pending, 2 — processing, 3 — completed, 4 — failed, 5 — reversed

description

string

transactions.description

Описание транзакции

created_at

datetime

transactions.created_at

Дата создания

updated_at

datetime

transactions.updated_at

Дата последнего обновления

is_recurring

bool

transactions.is_recurring

Флаг регулярности платежа

Пример PUT-запроса на изменение суммы транзакции на 0

PUT /api/v1/transactions/1 HTTP/1.1Host: your-api-domain.comContent-Type: application/json{  "type": 1,  "from_account_id": 1,  "to_account_id": 3,  "sum": 0.00,  "currency_id": 1,  "description": "Перевод другу (сумма исправлена)",  "is_recurring": false}

Пример ответа (422 Unprocessable Entity)

{  "error": "Сумма должна быть больше 0"}

Чек-лист для проверки ТЗ

  1. Полнота описания методов

    • Для каждого метода указан URL и HTTP-метод (GET, POST, PUT, DELETE)

    • Для каждого кода ошибки есть описание (когда возникает)

    • Есть примеры запросов и ответов (хотя бы один на каждый метод)

  2. Модели данных и маппинг

    • Для каждого поля ответа указано, откуда оно берётся (таблица, поле, вычисление)

    • Если поле вычисляемое — описан алгоритм расчёта

    • Если данные запроса сохраняются в БД — указано, в какое поле и таблицу

  3. Бизнес-логика

    • Описаны бизнес-правила, которые должны выполняться при обработке запроса

    • Указаны все ограничения (например, сумма > 0, сумма не может быть отрицательной)

    • Описаны проверки, которые должны выполняться перед выполнением операции

    • Если операция идемпотентна — отражено в ТЗ

  4. Коды ответа и ошибки

    • Коды ответа — 200, 201, 400, 404, 500

    • Описана обработка всех невалидных данных (ошибки валидации)

    • Описана обработка ошибок на уровне бизнес-логики

    • Указан статус-код и тело ответа для каждой ошибки (желательно с примером)

ссылка на оригинал статьи https://habr.com/ru/articles/1053910/