Back to skills
SKILL.md
Api Design
ASecurityПроектирование HTTP API — REST-конвенции (ресурсы, методы, статус-коды), пагинация (cursor vs offset), версионирование, идемпотентность (Idempotency-Key), формат ошибок RFC 7807 (problem+json), безопасность и rate limiting. Use при проектировании, ревью или версионировании API и эндпоинтов, выборе кодов ошибок, пагинации, лимитов или формата ответа.
- 2 stars
- 0 votes
- 0 copies
- 0 views
- Added September 11, 2026
Works with
Security analysis
100/100npx -y skills add Vitammiin/agent-vorcl-flow --skill api-design --agent claude-codeAre you the author of Api Design?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/vitammiin-api-design)---
name: api-design
description: Проектирование HTTP API — REST-конвенции (ресурсы, методы, статус-коды), пагинация (cursor vs offset), версионирование, идемпотентность (Idempotency-Key), формат ошибок RFC 7807 (problem+json), безопасность и rate limiting. Use при проектировании, ревью или версионировании API и эндпоинтов, выборе кодов ошибок, пагинации, лимитов или формата ответа.
---
# Навык: API Design
## REST-конвенции
Ресурсы — существительные во множественном числе; действие выражает HTTP-метод, не URL (`POST /orders`, а не `POST /createOrder`). Вложенность — максимум один уровень (`/users/{id}/orders`), глубже — фильтром (`/orders?userId=`). Действие вне CRUD — суб-ресурсом: `POST /orders/{id}/cancel`.
| Метод | Семантика | Идемпотентен | Успех | Типичные ошибки |
|---|---|---|---|---|
| GET | чтение | ✅ | 200 | 404 |
| POST | создание / действие | ❌ | 201 (+ `Location`) или 200 | 400, 409, 422 |
| PUT | полная замена | ✅ | 200 | 404, 409 |
| PATCH | частичное обновление | ❌ | 200 | 404, 409, 422 |
| DELETE | удаление | ✅ | 204 | 404 |
Статусы ошибок: 400 — синтаксически кривой запрос; 422 — валидный JSON, не прошедший бизнес-валидацию; 401 — не аутентифицирован; 403 — аутентифицирован, но нельзя; 409 — конфликт состояния (дубликат, устаревшая версия); 429 — превышен лимит (+ `Retry-After`).
## Пагинация
| | Offset (`?page=3&limit=20`) | Cursor (`?cursor=xyz&limit=20`) |
|---|---|---|
| Простота | ✅ проще, произвольная страница | сложнее, только «дальше» |
| Стабильность при вставках/удалениях | ❌ дубли и пропуски между страницами | ✅ стабильна |
| Скорость на глубине | ❌ `OFFSET 100000` читает и выбрасывает | ✅ `WHERE (sort_key, id) < cursor` по индексу |
| Когда | админки, маленькие статичные списки | ленты, публичные API, большие/живые данные |
Cursor — непрозрачная строка (base64 от `(sort_key, id)`), клиент её не парсит. Ответ списка — конверт: `{ "data": […], "nextCursor": "…", "hasMore": true }`. Лимит — с дефолтом и максимумом (например 20/100).
## Версионирование
- Ломающее (удаление/переименование поля, смена типа или семантики) — только в новой версии. Добавление опциональных полей — не ломающее, версии не требует.
- Дефолт — версия в пути: `/v1/…` (явно, кэшируемо, просто в роутинге). Альтернатива — заголовок (`Accept: …;version=2`) для чистых URL.
- Клиент — tolerant reader: неизвестные поля ответа игнорирует, тогда добавления безопасны.
- Старую версию не бросай молча: `Deprecation`/`Sunset`-заголовки, срок жизни, заметки по миграции.
## Идемпотентность
- GET/PUT/DELETE идемпотентны по контракту — клиент может безопасно ретраить.
- POST с побочным эффектом (платёж, заказ) — **Idempotency-Key**: клиент шлёт уникальный ключ заголовком; сервер хранит `key → результат` (Redis/БД, TTL ~24ч) и на повтор возвращает сохранённый ответ, не выполняя операцию дважды. Обязателен для денежных операций и любых ретраящихся вызовов (вебхуки, очереди).
- Потребители очередей — идемпотентны всегда: at-least-once означает, что дубли будут.
## Ошибки: RFC 7807 (application/problem+json)
Единый формат всех ошибок API:
```json
{
"type": "https://api.example.com/errors/insufficient-funds",
"title": "Insufficient funds",
"status": 422,
"detail": "Balance 5.00 is less than order total 20.00",
"instance": "/orders/req-7f3a",
"code": "INSUFFICIENT_FUNDS",
"errors": [{ "field": "amount", "message": "…" }]
}
```
- `code` — стабильный машинный код: по нему ветвится клиент; человекочитаемый текст может меняться и локализоваться.
- Валидационные ошибки — списком по полям, все сразу, не по одной.
- Не течь внутренностями: stack trace, SQL, имена таблиц — только в логи; наружу — generic 500 + `instance`/requestId для соотнесения с логами.
## Пример хорошего эндпоинта
```
POST /v1/orders
Authorization: Bearer <token>
Idempotency-Key: 3f2a-…
{ "items": [{ "productId": "p_1", "qty": 2 }] }
201 Created
Location: /v1/orders/ord_9x1
{ "id": "ord_9x1", "status": "pending", "total": { "amount": 4200, "currency": "EUR" }, "createdAt": "2026-08-06T10:00:00Z" }
```
Деньги — минорными единицами + валюта (не float); даты — ISO 8601 в UTC; id — префиксованные строки. Ошибка того же эндпоинта — problem+json с 422 и машинным `code`.
## Безопасность (минимум)
Аутентификация на каждом эндпоинте (Bearer/JWT), авторизация — на уровне ресурса (чужой `orderId` → 403/404), rate limiting per-user/per-key с 429, вход валидируется схемой (zod) до бизнес-логики.
## Углублённо
- REST vs GraphQL vs gRPC: GraphQL — клиенты с разными потребностями в данных; gRPC — внутренняя сервис-сервис связь с жёсткими контрактами; дефолт публичного API — REST.
- Контракты и OpenAPI-покрытие → `$swagger-coverage`.
- Коды и обработка ошибок → `$error-handling`.
- Локализация ответов (i18n) → `$i18n`: контракт ошибок — стабильный машинный `code` + параметры (не готовый переведённый текст), выбор языка по `Accept-Language`/локали пользователя.
Attribution
Comments
Loading comments…