Практические паттерны API
Единый формат ответа
Один и тот же формат во всех эндпоинтах упрощает клиенту жизнь:
{
"data": {...},
"meta": {...}
}
Для ошибок:
{
"message": "...",
"errors": {...}
}
Именование эндпоинтов
- Ресурсы во множественном числе:
/posts,/users - Вложенность:
/posts/{post}/comments - Действия над ресурсом выражаются методом, а не URL:
DELETE /posts/5, а неPOST /posts/5/delete
Исключения
Иногда действие не вписывается в CRUD. Тогда используют глагол:
POST /posts/{post}/publish
POST /posts/{post}/archive
POST /users/{user}/ban
Версионирование с самого начала
Даже если сейчас одна версия — заложи /v1. Добавить версию потом сложнее.
Частичное обновление
PATCH — для частичного обновления. PUT — для полного:
public function update(PatchPostRequest $request, Post $post)
{
$post->update($request->validated());
return new PostResource($post);
}
Идемпотентность
POST не идемпотентен: два одинаковых запроса создадут две записи. Для платежей и заказов используют idempotency key:
$key = $request->header('Idempotency-Key');
if ($key && Cache::has("idem:{$key}")) {
return Cache::get("idem:{$key}");
}
// обработка
$response = new OrderResource($order);
if ($key) {
Cache::put("idem:{$key}", $response, now()->addDay());
}
return $response;
Rate limiting
Ограничение частоты запросов защищает от злоупотреблений:
Route::middleware('throttle:60,1')->group(function () {
Route::apiResource('posts', PostController::class);
});
Для аутентифицированных клиентов лимит выше:
RateLimiter::for('api', function ($request) {
return $request->user()
? Limit::perMinute(1000)->by($request->user()->id)
: Limit::perMinute(60)->by($request->ip());
});
CORS
Если фронт на другом домене — нужен CORS. Laravel настраивается в config/cors.php:
'allowed_origins' => ['https://app.example.com'],
'allowed_methods' => ['*'],
'allowed_headers' => ['*'],
'supports_credentials' => true,
Кеширование
Ответы API можно кешировать:
return Cache::remember('posts.index', 3600, function () {
return PostResource::collection(Post::all());
});
Итоги
- API — это контракт между сервером и клиентами
- Ресурсы проектируются вокруг сущностей, а не URL
- Версионирование закладывается сразу
- Ошибки возвращаются в едином формате
- Аутентификация — через токены
- Документация обязательна
- Rate limiting защищает от злоупотреблений