Format Respons API: Praktik Terbaik untuk API yang Konsisten
Respons API yang tidak konsisten adalah keluhan utama dari pengembang frontend. Ketika setiap endpoint mengembalikan data dalam bentuk yang berbeda, kode klien dipenuhi dengan kasus-kasus khusus. Format respons yang konsisten meningkatkan pengalaman pengembang, mengurangi bug, dan membuat API Anda terdokumentasi sendiri.
Envelope Respons
Bungkus setiap respons dalam struktur yang konsisten:
Sukses (Sumber Daya Tunggal)
{
"data": {
"id": "user_123",
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
},
"meta": {
"requestId": "req_abc123"
}
}
Sukses (Koleksi)
{
"data": [
{ "id": "user_123", "name": "Alice" },
{ "id": "user_456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"perPage": 20,
"requestId": "req_def456"
}
}
Error
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
},
"meta": {
"requestId": "req_ghi789"
}
}
Prinsip utamanya: klien selalu memeriksa data atau error di tingkat teratas. Jangan pernah mencampurkan data sukses dan informasi error dalam respons yang sama.
Validasi format respons Anda dengan JSON Validator kami.
Kode Status HTTP
Gunakan kode status dengan benar — kode status adalah hal pertama yang diperiksa klien:
Kode Sukses
| Kode | Kapan Digunakan |
|---|---|
| 200 OK | GET berhasil, PUT/PATCH berhasil |
| 201 Created | POST yang membuat sumber daya |
| 204 No Content | DELETE berhasil (tanpa body) |
Kode Error Klien
| Kode | Kapan Digunakan |
|---|---|
| 400 Bad Request | Sintaks permintaan tidak valid |
| 401 Unauthorized | Autentikasi tidak ada atau tidak valid |
| 403 Forbidden | Terautentikasi tetapi tidak diotorisasi |
| 404 Not Found | Sumber daya tidak ditemukan |
| 409 Conflict | Konflik status sumber daya (duplikat) |
| 422 Unprocessable | Sintaks valid tetapi ada kesalahan semantik |
| 429 Too Many Requests | Batas laju terlampaui |
Kode Error Server
| Kode | Kapan Digunakan |
|---|---|
| 500 Internal Server Error | Kegagalan server yang tidak terduga |
| 502 Bad Gateway | Kegagalan layanan upstream |
| 503 Service Unavailable | Kelebihan beban sementara atau pemeliharaan |
Desain Respons Error
Respons error yang baik membantu pengembang melakukan debug dengan cepat:
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "User with ID 'user_999' not found",
"details": [],
"documentationUrl": "https://api.example.com/docs/errors#RESOURCE_NOT_FOUND"
},
"meta": {
"requestId": "req_xyz789",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Aturan:
codedapat dibaca mesin (string konstan, bukan status HTTP)messagedapat dibaca manusia (bisa berubah tanpa merusak klien)detailsmenyediakan error tingkat field untuk kegagalan validasirequestIdmemungkinkan tim dukungan melacak permintaan di log
Pola Paginasi
Berbasis Offset
Sederhana dan mendukung lompatan ke halaman sembarang:
{
"data": ["..."],
"meta": {
"page": 2,
"perPage": 20,
"total": 142,
"totalPages": 8
},
"links": {
"first": "/api/users?page=1&per_page=20",
"prev": "/api/users?page=1&per_page=20",
"next": "/api/users?page=3&per_page=20",
"last": "/api/users?page=8&per_page=20"
}
}
Berbasis Kursor
Lebih baik untuk data real-time dan dataset besar:
{
"data": ["..."],
"meta": {
"hasNext": true,
"hasPrev": true
},
"links": {
"next": "/api/users?cursor=eyJpZCI6MTQzfQ&limit=20",
"prev": "/api/users?cursor=eyJpZCI6MTIzfQ&limit=20&direction=prev"
}
}
Tanggal dan Waktu
Selalu gunakan ISO 8601 dengan informasi zona waktu:
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:33+00:00",
"expiresAt": "2024-12-31T23:59:59Z"
}
Jangan pernah menggunakan:
- Unix timestamp (ambigu: detik atau milidetik?)
- Tanggal lokal tanpa zona waktu
- Format kustom seperti MM/DD/YYYY
Untuk informasi lebih lanjut tentang penanganan timestamp, lihat panduan Unix Timestamps kami.
Null vs Field yang Tidak Ada
Dua pendekatan umum:
Sertakan dengan null (eksplisit):
{ "name": "Alice", "avatar": null, "bio": null }
Hapus field yang tidak ada (sparse):
{ "name": "Alice" }
Rekomendasi: Konsisten dalam API Anda. Null eksplisit lebih baik untuk bahasa bertipe (klien tahu field tersebut ada). Sparse lebih baik untuk lingkungan dengan keterbatasan bandwidth.
Versioning Respons
Ketika format respons berubah, beri versi pada API Anda:
GET /api/v2/users/123
Perubahan yang merusak yang memerlukan versioning:
- Menghapus field
- Mengubah tipe field
- Mengganti nama field
- Mengubah struktur envelope respons
Perubahan yang tidak merusak (aman tanpa versioning):
- Menambahkan field baru
- Menambahkan endpoint baru
- Menambahkan nilai enum baru
FAQ
Haruskah saya membungkus respons sukses dalam key data atau mengembalikan sumber daya secara langsung?
Menggunakan pembungkus data menyediakan struktur yang konsisten untuk semua respons dan menyisakan ruang untuk metadata, paginasi, dan tautan di samping data. Mengembalikan sumber daya secara langsung lebih sederhana untuk endpoint sumber daya tunggal. Sebagian besar API modern menggunakan pendekatan pembungkus untuk konsistensi.
Bagaimana cara menangani kegagalan parsial dalam operasi batch?
Kembalikan 200 dengan respons yang menyertakan keberhasilan dan kegagalan dalam objek data. Menggunakan 207 Multi-Status (WebDAV) adalah opsi lain tetapi kurang umum digunakan dalam REST API.
Sumber Terkait
- JSON Formatter — Format respons API
- Pola Desain JSON API — Panduan desain API yang komprehensif
- Validasi JSON Schema — Validasi struktur respons