Pola Desain JSON API: Membangun REST API yang Lebih Baik
API yang dirancang dengan baik menyenangkan untuk digunakan. Yang dirancang buruk menciptakan bug, frustrasi, dan utang teknis. Panduan ini membahas pola-pola teruji untuk merancang JSON REST API yang konsisten, mudah ditemukan, dan mudah dipelihara.
Penamaan Resource
Resource adalah kata benda, bukan kata kerja. Gunakan kata benda jamak untuk koleksi dan resource tunggal melalui ID:
GET /api/users # Daftar pengguna
POST /api/users # Buat pengguna
GET /api/users/123 # Ambil pengguna 123
PUT /api/users/123 # Perbarui pengguna 123
DELETE /api/users/123 # Hapus pengguna 123
Konvensi penamaan:
- Gunakan huruf kecil dengan tanda hubung:
/api/blog-posts(bukanblogPostsataublog_posts) - Sarangkan resource terkait:
/api/users/123/orders - Batasi penyarangan hingga 2 tingkat:
/api/users/123/orders/456(tidak lebih dalam) - Hindari kata kerja di URL:
/api/users/123/activatedapat diterima untuk aksi yang tidak dipetakan ke CRUD
Envelope Respons
Bungkus respons dalam envelope yang konsisten:
{
"data": {
"id": "123",
"type": "user",
"attributes": {
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}
},
"meta": {
"requestId": "req_abc123"
}
}
Untuk koleksi:
{
"data": [
{ "id": "123", "name": "Alice" },
{ "id": "456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"perPage": 20
}
}
Validasi respons API Anda dengan JSON Validator kami untuk memastikan sesuai dengan skema Anda.
Paginasi
Tiga pendekatan umum:
Berbasis Offset (Paling Sederhana)
GET /api/users?page=2&per_page=20
{
"data": [...],
"meta": {
"page": 2,
"perPage": 20,
"total": 142,
"totalPages": 8
}
}
Kelebihan: Sederhana, mendukung lompat ke halaman mana pun. Kekurangan: Hasil tidak konsisten dengan insert/delete bersamaan.
Berbasis Cursor (Paling Andal)
GET /api/users?cursor=eyJpZCI6MTIzfQ&limit=20
{
"data": [...],
"meta": {
"hasNext": true,
"nextCursor": "eyJpZCI6MTQzfQ"
}
}
Kelebihan: Konsisten dengan perubahan bersamaan, performa baik pada dataset besar. Kekurangan: Tidak dapat melompat ke halaman sembarang.
Berbasis Keyset (Paling Performa)
GET /api/users?after_id=123&limit=20
Menggunakan ID item terakhir (atau field terurut lainnya) untuk mengambil halaman berikutnya. Mirip dengan berbasis cursor tetapi dengan parameter yang transparan.
Rekomendasi: Gunakan berbasis cursor untuk feed real-time dan dataset besar. Gunakan berbasis offset untuk dashboard admin di mana perpindahan halaman penting.
Pemfilteran dan Pengurutan
Pemfilteran
GET /api/users?status=active&role=admin
GET /api/users?created_after=2024-01-01
GET /api/users?search=alice
Untuk filter kompleks, pertimbangkan parameter query khusus:
GET /api/users?filter[status]=active&filter[role]=admin
Pengurutan
GET /api/users?sort=name # Menaik
GET /api/users?sort=-created_at # Menurun (awali dengan -)
GET /api/users?sort=-created_at,name # Beberapa field
Penanganan Error
Respons error yang konsisten sangat penting untuk kegunaan API:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Must be a valid email address",
"value": "not-an-email"
},
{
"field": "age",
"message": "Must be between 0 and 150",
"value": -5
}
]
},
"meta": {
"requestId": "req_abc123"
}
}
Kode status HTTP yang digunakan:
| Kode | Arti | Kapan |
|---|---|---|
| 200 | OK | GET, PUT berhasil |
| 201 | Created | POST berhasil |
| 204 | No Content | DELETE berhasil |
| 400 | Bad Request | Error validasi |
| 401 | Unauthorized | Auth hilang/tidak valid |
| 403 | Forbidden | Auth valid, izin tidak cukup |
| 404 | Not Found | Resource tidak ada |
| 409 | Conflict | Resource duplikat, konflik versi |
| 422 | Unprocessable | Secara semantik tidak valid |
| 429 | Too Many Requests | Batas rate terlampaui |
| 500 | Internal Error | Error server yang tidak terduga |
Versioning
Tiga pendekatan:
Path URL (Direkomendasikan)
GET /api/v1/users
GET /api/v2/users
Kelebihan: Eksplisit, mudah dirutekan, mudah diuji.
Berbasis Header
GET /api/users
Accept: application/vnd.myapi.v2+json
Kelebihan: URL bersih. Kekurangan: Lebih sulit diuji, kurang mudah ditemukan.
Parameter Query
GET /api/users?version=2
Kelebihan: Mudah diuji. Kekurangan: Semantik parameter opsional.
Rekomendasi: Versioning path URL adalah pilihan paling praktis. Eksplisit, dapat di-cache, dan berfungsi dengan setiap alat HTTP.
Penanganan Tanggal dan Waktu
Selalu gunakan ISO 8601 dalam UTC:
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:33Z",
"expiresAt": "2024-12-31T23:59:59Z"
}
Jangan pernah gunakan Unix timestamp dalam respons API — mereka ambigu (detik vs milidetik) dan tidak mudah dibaca manusia. Untuk lebih lanjut tentang penanganan timestamp, lihat panduan Unix Timestamps kami.
Pembatasan Rate
Komunikasikan batas rate di header respons:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 67
X-RateLimit-Reset: 1705312800
Retry-After: 30
Kembalikan 429 Too Many Requests saat batas terlampaui, dengan pesan error yang jelas dan header Retry-After.
HATEOAS (Opsional tetapi Powerful)
Sertakan tautan ke resource dan aksi terkait:
{
"data": {
"id": "123",
"name": "Alice",
"links": {
"self": "/api/users/123",
"orders": "/api/users/123/orders",
"avatar": "/api/users/123/avatar"
}
}
}
Ini membuat API Anda self-documenting dan mengurangi konstruksi URL di sisi klien.
FAQ
Haruskah saya menggunakan spesifikasi JSON:API atau merancang format sendiri?
Spesifikasi JSON:API (jsonapi.org) menyediakan standar yang komprehensif, tetapi bisa verbose untuk API sederhana. Untuk sebagian besar proyek, merancang format kustom yang lebih sederhana mengikuti pola-pola dalam panduan ini lebih praktis. Gunakan JSON:API jika Anda membutuhkan library klien otomatis dan standar yang ketat.
Bagaimana seharusnya saya menangani pembaruan parsial (PATCH vs PUT)?
Gunakan PUT untuk penggantian resource lengkap (klien mengirim semua field). Gunakan PATCH untuk pembaruan parsial (klien mengirim hanya field yang berubah). PATCH dengan JSON Merge Patch (RFC 7396) adalah pendekatan paling sederhana: kirim objek JSON dengan hanya field yang akan diperbarui, dan null untuk menghapus field.
Sumber Terkait
- JSON Formatter — Format respons API agar mudah dibaca
- Panduan Validasi JSON Schema — Validasi payload API dengan JSON Schema
- Penjelasan JWT Token — Amankan API Anda dengan JSON Web Token