Belajar Backend Developer - REST API Design
Episode 4 of 28

Belajar Backend Developer - REST API Design

Mendesain REST API yang benar: modeling resource, pemilihan metode dan status code yang tepat, versioning, pagination, error format yang konsisten, dan best practices, dengan studi kasus desain API toko online

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Setelah di episode 2 kalian memahami HTTP dan di episode 3 memilih bahasa, sekarang saatnya menjawab pertanyaan paling penting bagi seorang backend developer: bagaimana mendesain API yang enak dipakai? Banyak API yang "berfungsi" tapi menyakitkan bagi konsumennya — status code salah, format error tidak konsisten, resource yang membingungkan.

Mengapa desain API penting? Karena API adalah kontrak jangka panjang. Sekali dipakai mobile app dan partner bisnis, mengubahnya berarti melanggar janji. Desain yang buruk memaksa tim lain menulis workaround; desain yang baik membuat integrasi mengalir. Episode ini membangun fondasi desain REST yang akan kalian pakai sepanjang series dan di dunia kerja.

Prinsip Dasar REST

REST (Representational State Transfer) sederhananya: modelkan dunia nyata sebagai resource, dan akses resource itu lewat URL + metode HTTP. Prinsip kuncinya:

  • Resource adalah kata benda (products, orders), bukan kata kerja (getProducts, createOrder).
  • Aksi diekspresikan dengan metode HTTP (GET, POST, PUT, PATCH, DELETE).
  • State tidak disimpan di server per request (stateless) — setiap request membawa semua yang dibutuhkan.

Resource Modeling

Pertama, identifikasi resource inti dari domain bisnis. Untuk toko online kita:

ResourceRepresentasiContoh URL
Produkproducts/products, /products/42
Orderorders/orders, /orders/87
Userusers/users/5
Item dalam orderNested/orders/87/items
Ulasan produkNested/products/42/reviews

Aturan emas nested resource: gunakan nesting hanya untuk resource yang tidak berdiri sendiri (item order tanpa order tidak masuk akal). Kalau resource hidup mandiri, jangan paksa nesting.

Rencana Endpoint

Pola CRUD standar untuk satu resource products:

MetodeURLTujuanStatus sukses
GET/productsDaftar produk200
GET/products/{id}Detail produk200
POST/productsBuat produk201
PUT/products/{id}Ganti produk200
PATCH/products/{id}Ubah sebagian200
DELETE/products/{id}Hapus produk204

Konsisten dengan tabel ini di seluruh resource. Jika semua resource mengikuti pola yang sama, konsumen API bisa menebak endpoint tanpa dokumentasi.

Status Code yang Benar

Tiga kesalahan paling umum dalam memilih status code:

  1. Semua error = 400. Format salah (400), belum login (401), tidak diizinkan (403), dan tidak ditemukan (404) punya makna berbeda — konsumen API bergantung pada perbedaan itu untuk logic.
  2. Sukses create = 200. POST /products yang berhasil harus 201 Created, bukan 200 OK — dan sebaiknya membawa header Location menunjuk resource baru.
  3. Lupa 409. Konflik bisnis seperti stok habis saat checkout atau email sudah terdaftar adalah 409 Conflict, bukan 400.
text
GET /products/999          → 404
POST /orders tanpa auth    → 401
POST /orders stok habis    → 409
POST /products (berhasil)  → 201

Format Error yang Konsisten

Konsumen API harus bisa memparsing error secara seragam. Tetapkan satu format dan gunakan di semua endpoint:

Format error standar
{
  "error": "VALIDATION_FAILED",
  "message": "Nama produk wajib diisi",
  "details": [
    { "field": "name", "reason": "required" },
    { "field": "price", "reason": "must_be_positive" }
  ]
}

error adalah kode mesin yang stabil (jangan diubah, karena dipakai untuk logic), message untuk dibaca manusia, dan details opsional untuk field-level error. Format konsisten ini dibangun menjadi error handler terpusat di episode 11.

Note

Gunakan kode mesin (VALIDATION_FAILED) alih-alih menebak-nebak string untuk parsing di client. String rawan typo dan berubah; kode mesin adalah kontrak. Ini juga menjadi dasar kontrak testing di episode 8.

Pagination

Daftar resource yang panjang tidak boleh dikembalikan sekaligus. Dua pola paling umum:

text
# Berbasis page (sederhana, stabil)
GET /products?page=2&limit=20
 
# Berbasis cursor (konsisten saat data berubah)
GET /products?cursor=eyJpZCI6NDJ9&limit=20

Cursor pagination lebih unggul untuk data yang sering berubah (produk baru masuk terus): posisi tidak "melompat" seperti page. Respons dengan metadata:

Respons pagination
{
  "data": [ { "id": 42, "name": "Keyboard" } ],
  "meta": { "page": 2, "limit": 20, "total": 103 }
}

Versioning

API yang sudah dipakai publik suatu saat harus berubah. Versioning memberi ruang untuk berubah tanpa merusak konsumen lama. Pendekatan paling umum adalah URL path versioning:

text
https://api.example.com/v1/products
https://api.example.com/v2/products

v1 dibiarkan hidup untuk konsumen lama; v2 membawa kontrak baru. Kebijakan penting: beri masa tenggang dan jadwalkan deprecation. Mulai v1 sejak API pertama dirilis — menambah versioning belakangan jauh lebih menyakitkan.

Tip

Jangan versioning terlalu dini (saat masih berubah tiap sprint) dan jangan terlalu lambat (saat 50 konsumen sudah terikat). Aturan praktis: buka v1 begitu API dipakai tim luar atau produksi, dan komunikasikan deprecation minimal 6 bulan sebelumnya.

Praktik: Desain API Toko Online

Mari desain API lengkap untuk toko online kita. Skema resource:

text
/users          → daftar & kelola akun
/users/{id}     → detail akun
/products       → daftar & kelola produk
/products/{id}  → detail produk
/products/{id}/reviews → ulasan per produk
/orders         → buat & lihat order
/orders/{id}    → detail order
/orders/{id}/items → item dalam order

Desain beberapa flow:

Flow belanja dengan REST
curl -s http://localhost:3000/v1/products?limit=10
curl -s -X POST http://localhost:3000/v1/orders \
  -H "Content-Type: application/json" \
  -d '{"items":[{"productId":1,"qty":2}]}'
curl -s http://localhost:3000/v1/orders/87

Flow ini: GET produk → POST order → GET detail order. Ketiga endpoint mengikuti pola tabel CRUD di atas — konsumen sudah bisa menebak tanpa dokumentasi.

Common Pitfalls

Kata Kerja di URL

/getProducts atau /createOrder adalah pelanggaran REST — method HTTP sudah menyatakan aksi. Gunakan GET /products dan POST /orders.

Lupa Idempotency pada Order

Client retry saat network putus bisa membuat order ganda. Solusi umum: idempotency key — client mengirim header Idempotency-Key, server menolak duplikat dengan 409. Episode 10 membahas ini untuk pembayaran.

Nested yang Berlebihan

/users/5/orders/87/items/3 terlalu dalam. Batasi nesting dua level; untuk resource yang hidup mandiri, gunakan root resource dengan filter.

Penutup

Episode 4 membangun kontrak API: prinsip REST dengan resource sebagai kata benda, pola CRUD yang konsisten, status code yang tepat, format error seragam, pagination, dan versioning — diterapkan pada desain API toko online.

Inti yang harus dibawa pulang:

  • Resource = kata benda, aksi = metode HTTP; hindari kata kerja di URL.
  • Status code harus tepat: 201 untuk create, 401 vs 403 untuk auth, 409 untuk konflik.
  • Format error konsisten dengan kode mesin untuk memudahkan parsing.
  • Pagination wajib untuk list; cursor lebih stabil untuk data yang sering berubah.
  • Versioning (/v1, /v2) memberi ruang berubah tanpa merusak konsumen.

Di episode 5 selanjutnya kita akan menata rumah data: SQL & database dasar — modeling skema, query, indexing, dan transaction, lengkap dengan praktik membangun skema produk dan order di PostgreSQL. Sampai jumpa di episode 5!