Lewati ke isi

02 โ€” REST API

โ† Pengantar | Index | Lanjut: Database โ†’


2.1 Sebelum API: Bagaimana Web Bekerja

Saat Anda membuka tokoku.com, urutan kejadiannya:

Browser (Client)                                    Server
     โ”‚                                                 โ”‚
     โ”‚ 1. DNS lookup: "tokoku.com itu IP berapa?"      โ”‚
     โ”‚    โ†’ dijawab DNS server: 103.10.20.30           โ”‚
     โ”‚                                                 โ”‚
     โ”‚ 2. HTTP Request โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ  โ”‚
     โ”‚    GET /products                                โ”‚ 3. Server memproses:
     โ”‚                                                 โ”‚    - jalankan kode backend
     โ”‚                                                 โ”‚    - query database
     โ”‚ 4. HTTP Response โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”‚    - susun response
     โ”‚    200 OK + data                                โ”‚
     โ–ผ                                                 โ–ผ
  5. Browser merender halaman

๐Ÿ“Œ Wajib paham โ€” pemisahan Client & Server:

  • Client = yang meminta (browser, aplikasi mobile, frontend Next.js/Nuxt, bahkan server lain).
  • Server = yang melayani (backend: Laravel, Express, Strapi, dsb.).
  • Keduanya berkomunikasi lewat protokol HTTP dengan format pesan yang disepakati โ€” dan kesepakatan itulah yang disebut API.

2.2 Apa Itu API?

API (Application Programming Interface) adalah kontrak komunikasi antara dua sistem. Analogi paling gampang: pelayan restoran.

  • Anda (client/frontend) memesan makanan lewat pelayan.
  • Pelayan (API) meneruskan pesanan ke dapur dengan format yang dipahami dapur.
  • Dapur (server/backend) memasak dan mengembalikan makanan lewat pelayan.

Anda tidak perlu tahu cara dapur bekerja โ€” cukup tahu format pesanannya (menu = dokumentasi API).

REST (Representational State Transfer) adalah gaya desain API paling umum di web, dengan prinsip: setiap hal adalah resource yang punya alamat (URL), dan aksi terhadapnya diekspresikan lewat HTTP method.

2.3 Anatomi Sebuah Request

POST https://api.tokoku.com/v1/orders?source=mobile
โ”‚    โ”‚     โ”‚              โ”‚  โ”‚      โ”‚
โ”‚    โ”‚     โ”‚              โ”‚  โ”‚      โ””โ”€โ”€ Query string
โ”‚    โ”‚     โ”‚              โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Path / endpoint
โ”‚    โ”‚     โ”‚              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Versi API
โ”‚    โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Domain (host)
โ”‚    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Protokol (HTTPS)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ HTTP Method

Headers:
  Content-Type: application/json        โ† "body-ku berformat JSON"
  Accept: application/json              โ† "aku ingin jawaban dalam JSON"
  Authorization: Bearer eyJhbGciOi...   โ† identitas/izin pemanggil

Body:
{
  "product_id": 123,
  "quantity": 2
}

Tiga tempat menaruh data โ€” dan kapan memakainya

Tempat Contoh Dipakai untuk
Path parameter /products/42 Mengidentifikasi resource spesifik
Query string /products?category=fashion&page=2 Filter, sort, pagination, opsi โ€” hal yang memodifikasi cara membaca
Body {"name": "Kaos", "price": 75000} Data yang dikirim/diubah (POST/PUT/PATCH)

โš ๏ธ Red flag: data sensitif (password, token, NIK) di query string. URL tercatat di log server, browser history, dan analytics โ€” data sensitif harus di body atau header.

2.4 Anatomi Sebuah Response

HTTP/1.1 201 Created                    โ† Status line
Headers:
  Content-Type: application/json
  X-RateLimit-Remaining: 58             โ† sisa kuota request

Body:
{
  "data": {
    "id": 1001,
    "product_id": 123,
    "quantity": 2,
    "total": 150000,
    "status": "pending",
    "created_at": "2026-07-06T10:30:00Z"
  }
}

Format error yang baik โ€” konsisten dan informatif tanpa membocorkan internal:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Data yang dikirim tidak valid.",
    "details": {
      "quantity": ["Minimal 1."],
      "product_id": ["Produk tidak ditemukan."]
    }
  }
}

2.5 HTTP Methods

Method Fungsi Idempotent?* Contoh
GET Membaca data โœ… GET /products โ†’ daftar produk
POST Membuat data baru โŒ POST /orders โ†’ buat order
PUT Mengganti seluruh resource โœ… PUT /users/5 โ†’ timpa semua field user 5
PATCH Mengubah sebagian resource โŒ** PATCH /users/5 โ†’ ubah nomor HP saja
DELETE Menghapus resource โœ… DELETE /orders/99

๐Ÿ“Œ Idempotent = dipanggil 1x atau 10x hasil akhirnya sama. Ini penting untuk retry: kalau koneksi putus dan client mengulang request, PUT /users/5 aman diulang; POST /orders tidak โ€” bisa jadi order dobel. Karena itu sistem pembayaran memakai idempotency key* (ID unik per percobaan) agar retry tidak menduplikasi transaksi.

**PATCH umumnya idempotent dalam praktik, tapi tidak dijamin oleh spesifikasi.

โš ๏ธ Red flag: endpoint GET yang mengubah data (misal GET /delete-user?id=5). Selain melanggar konvensi, ini berbahaya: crawler, prefetch browser, atau preview link di chat bisa "tidak sengaja" memanggilnya dan menghapus data sungguhan.

2.6 HTTP Status Codes

Range Arti Kode Penting
2xx โœ… Sukses 200 OK ยท 201 Created (resource baru dibuat) ยท 204 No Content (sukses, tanpa body โ€” umum untuk DELETE)
3xx โ†ช๏ธ Redirect 301 Moved Permanently ยท 304 Not Modified (pakai cache)
4xx โŒ Kesalahan client 400 ยท 401 ยท 403 ยท 404 ยท 409 Conflict (data bentrok, mis. email sudah terdaftar) ยท 422 ยท 429
5xx ๐Ÿ’ฅ Kesalahan server 500 Internal Server Error ยท 502 Bad Gateway ยท 503 Service Unavailable ยท 504 Gateway Timeout

Pasangan yang sering tertukar

401 Unauthorized vs 403 Forbidden
"Kamu belum login / token invalid" "Kamu sudah login, tapi tidak berhak"
400 Bad Request vs 422 Unprocessable Entity
Format request rusak (JSON tidak valid) Format benar, isinya tidak valid (email tanpa @)
502 Bad Gateway vs 504 Gateway Timeout
Server di belakang proxy mati/error Server di belakang proxy terlalu lama menjawab

Kenapa ini berguna untuk semua divisi: saat QA/PM melaporkan bug, menyebut "endpoint X return 403" jauh lebih actionable daripada "errornya merah". Dan saat mereview kode AI, Anda tahu response yang seharusnya.

โš ๏ธ Red flag: API yang selalu return 200 bahkan saat error, lalu error-nya disembunyikan di body ({"success": false}). Ini merusak monitoring, cache, dan retry logic โ€” semua tooling modern mengandalkan status code.

2.7 Desain Endpoint yang Baik (RESTful)

Prinsip inti: URL adalah kata benda (resource), method adalah kata kerja.

โœ… Baik                          โŒ Buruk
GET    /products                 GET  /getAllProducts
GET    /products/42              GET  /product?do=fetch&id=42
POST   /products                 POST /createNewProduct
PATCH  /products/42              POST /updateProduct
DELETE /products/42              GET  /deleteProduct?id=42
GET    /users/7/orders           GET  /getOrdersByUserId?uid=7
POST   /orders/1001/cancel*      GET  /cancelOrder?id=1001

*Untuk aksi yang tidak cocok jadi CRUD murni (cancel, publish, approve), konvensi umum: POST /resource/{id}/aksi.

Konvensi penting lainnya

  • Plural: /products bukan /product.
  • Versioning: /v1/products โ€” agar perubahan besar (breaking change) tidak merusak client lama. Client lama tetap di /v1, client baru pindah ke /v2.
  • Pagination untuk data banyak:
    GET /products?page=2&limit=20
    
    Response menyertakan metadata:
    { "data": [...], "meta": { "page": 2, "limit": 20, "total": 457, "total_pages": 23 } }
    
  • Filtering & sorting: GET /products?category=fashion&min_price=50000&sort=-price (tanda - = descending).
  • Konsistensi penamaan: pilih satu gaya (snake_case atau camelCase) untuk seluruh field JSON dan patuhi di semua endpoint.

โš ๏ธ Red flag: AI sering membuat endpoint baru dengan gaya berbeda dari endpoint yang sudah ada di project. Selalu beri konteks: "ikuti konvensi endpoint yang sudah ada di project ini" โ€” dan lampirkan contohnya.

2.8 Format Data: JSON

JSON (JavaScript Object Notation) โ€” format standar pertukaran data:

{
  "id": 42,
  "name": "Kaos Polos",
  "price": 75000,
  "discount": null,
  "is_available": true,
  "tags": ["fashion", "unisex"],
  "seller": {
    "id": 7,
    "name": "Vesstore"
  },
  "variants": [
    { "size": "M", "stock": 10 },
    { "size": "L", "stock": 3 }
  ]
}

Enam tipe data: string ("teks"), number (75000, 19.99), boolean (true/false), null, array ([...]), object ({...}).

Jebakan umum yang sering muncul di kode AI:

  • Angka vs string: "price": "75000" (string) membuat frontend harus konversi manual dan rawan bug perhitungan. Angka ya angka.
  • Uang & floating point: 0.1 + 0.2 = 0.30000000000000004 di banyak bahasa. Untuk uang, simpan sebagai integer satuan terkecil (Rp75.000 โ†’ 75000; $19.99 โ†’ 1999 sen).
  • Tanggal: pakai format ISO 8601 dalam UTC: "2026-07-06T10:30:00Z". Jangan "06/07/2026" โ€” ambigu (6 Juli atau 7 Juni?).
  • Boolean vs string: "is_available": "false" adalah string tidak kosong = truthy di JavaScript. Bug klasik.

2.9 Autentikasi API

Metode Cara Kerja Umum Dipakai Untuk
API Key Kunci statis di header (X-API-Key: abc123) Integrasi server-ke-server sederhana
Bearer Token / JWT Token berisi identitas user + masa berlaku Login user di web/mobile app
Session + Cookie Server menyimpan sesi, browser otomatis mengirim cookie Web app tradisional (server-rendered)
OAuth 2.0 Delegasi akses โ€” "Login with Google" tanpa berbagi password Integrasi pihak ketiga (marketplace, payment, dsb.)

JWT lebih dekat

Setelah login, server memberi token โ€” tiga bagian dipisah titik:

eyJhbGciOiJIUzI1NiJ9 . eyJ1c2VyX2lkIjo3LCJleHAiOjE3NTE4MDAwMDB9 . SflKxwRJSMeKKF2QT4f...
โ””โ”€โ”€โ”€โ”€ HEADER โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ PAYLOAD โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€ SIGNATURE โ”€โ”€โ”€โ”€โ”˜
 algoritma yang        isi klaim: user_id, role,             tanda tangan digital โ€”
 dipakai               expiry (exp)                          bukti token tidak diubah

๐Ÿ“Œ Wajib paham: payload JWT hanya di-encode (Base64), BUKAN dienkripsi โ€” siapa pun bisa membacanya (coba tempel di jwt.io). Signature hanya menjamin isinya tidak diubah. Karena itu: jangan pernah menaruh data sensitif di dalam JWT.

Alur token:

Login (email+password) โ†’ server beri access token (umur pendek, mis. 15 menit)
                          + refresh token (umur panjang, mis. 7 hari)

Setiap request         โ†’ Authorization: Bearer <access_token>
Access token expired   โ†’ tukar refresh token dengan access token baru (tanpa login ulang)
Refresh token expired  โ†’ user harus login ulang

Inilah kenapa aplikasi kadang "tiba-tiba logout" โ€” refresh token-nya kedaluwarsa atau di-revoke.

OAuth 2.0 sekilas

Saat aplikasi Anda perlu mengakses data user di layanan lain (misal: menarik data transaksi dari marketplace):

1. User diarahkan ke halaman login marketplace ("Izinkan Aplikasi X mengakses data ordermu?")
2. User setuju โ†’ marketplace memberi authorization code
3. Backend Anda menukar code itu dengan access token + refresh token
4. Backend memakai access token untuk memanggil API marketplace
5. Token expired โ†’ refresh secara terjadwal (biasanya via cron/scheduler)

Poin pentingnya: password user tidak pernah lewat aplikasi Anda โ€” itulah nilai OAuth.

2.10 REST vs Alternatif Lain (Sekilas)

Supaya tidak bingung saat AI atau tim menyebut istilah ini:

Karakteristik Kapan Dipakai
REST Resource + HTTP method, satu endpoint per resource Default untuk mayoritas API
GraphQL Satu endpoint, client menentukan sendiri field yang diminta Frontend butuh fleksibilitas tinggi, banyak variasi tampilan
WebSocket Koneksi dua arah yang terus terbuka Real-time: chat, notifikasi live, dashboard live
Webhook API "terbalik" โ€” server pihak lain memanggil endpoint kita saat ada event Notifikasi pembayaran, event dari marketplace

๐Ÿ“Œ Webhook penting dipahami: saat integrasi payment gateway, bukan kita yang bertanya "sudah dibayar belum?" berulang-ulang (polling) โ€” melainkan payment gateway yang memanggil endpoint kita begitu pembayaran masuk.

2.11 Dokumentasi & Testing API

Dokumentasi: OpenAPI / Swagger

Standar untuk mendokumentasikan API dalam format yang bisa dibaca manusia dan mesin. Dari satu file spesifikasi, bisa di-generate: halaman dokumentasi interaktif, client SDK, bahkan validasi otomatis.

๐Ÿ’ก Prompt: "Buatkan spesifikasi OpenAPI 3.0 untuk endpoint-endpoint berikut, lengkap dengan contoh request/response dan skema error."

Testing manual: curl & Postman

Semua orang (termasuk QA & PM) bisa mengetes API tanpa menunggu frontend jadi:

# GET sederhana
curl https://api.tokoku.com/v1/products

# POST dengan body dan auth
curl -X POST https://api.tokoku.com/v1/orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"product_id": 123, "quantity": 2}'

# Lihat status code & headers
curl -i https://api.tokoku.com/v1/products/42

Postman/Insomnia = curl dengan antarmuka visual: simpan koleksi request, kelola environment (staging vs production), dan bagikan ke tim.

๐Ÿงช Latihan: buka API publik gratis (misal https://api.github.com/users/octocat) lewat browser atau curl. Amati struktur JSON dan headers-nya.

2.12 Karakteristik Lain yang Perlu Diketahui

  • Stateless: tiap request REST berdiri sendiri โ€” server tidak "mengingat" request sebelumnya. Semua konteks (auth, dsb.) dibawa di setiap request. Inilah kenapa token dikirim berulang di setiap call.
  • Caching: response GET bisa di-cache (header Cache-Control, ETag) โ€” hemat beban server & mempercepat client.
  • Rate limiting: server membatasi jumlah request per client per waktu (429 Too Many Requests). Response biasanya menyertakan header X-RateLimit-Remaining dan Retry-After.
  • Timeout & retry: client yang baik menetapkan batas tunggu dan strategi ulang (dengan exponential backoff โ€” jeda makin lama tiap percobaan) โ€” dan hanya me-retry operasi yang idempotent (lihat ยง2.5).

2.13 Prompting AI untuk API

๐Ÿ’ก Contoh prompt lengkap:

"Di project Laravel 11 ini, buatkan REST API endpoint POST /v1/orders. Requirement: - Autentikasi Bearer token (Sanctum) - Validasi lewat FormRequest: product_id wajib & exists di tabel products, quantity wajib & minimal 1 - Bungkus pembuatan order + pengurangan stok dalam satu database transaction - Response 201 dengan data order; 422 bila validasi gagal atau stok kurang (sertakan detail per field); 404 bila produk tidak ditemukan - Format field response snake_case, tanggal ISO 8601 UTC, harga sebagai integer rupiah - Ikuti konvensi endpoint yang sudah ada di project (lihat routes/api.php)"

๐Ÿ’ก Prompt review: "Cek endpoint-endpoint ini terhadap konvensi REST: method sesuai aksi, status code tepat, tidak ada data sensitif di query string, dan penamaan konsisten. Daftar semua pelanggaran yang ditemukan."


2.14 ๐Ÿงช TUTORIAL PRAKTIK: Dari Nol Sampai Endpoint Pertama

Kerjakan berurutan. Estimasi 45โ€“60 menit. Butuh: terminal (curl sudah terpasang di Mac/Linux; Windows pakai PowerShell atau Git Bash) dan AI assistant.

Langkah 1 โ€” Rasakan API sungguhan (10 menit)

Panggil API publik GitHub dan amati semuanya:

curl -i https://api.github.com/users/octocat

Yang harus Anda temukan di output (checklist pengamatan):

  • [ ] Status line: HTTP/2 200
  • [ ] Header content-type: application/json
  • [ ] Header rate limit: x-ratelimit-remaining: ... (GitHub membatasi 60 request/jam tanpa auth)
  • [ ] Body JSON: temukan field bertipe string, number, null, dan URL ke resource lain

Sekarang picu error dengan sengaja โ€” ini kebiasaan penting:

curl -i https://api.github.com/users/user-yang-tidak-mungkin-ada-99xx
  • [ ] Statusnya 404 dan body error-nya tetap JSON yang rapi โ€” bukan halaman HTML error. Begitulah API yang baik gagal.

Langkah 2 โ€” Tulis kontrak SEBELUM kode (15 menit)

Ini kebiasaan yang membedakan hasil vibe coding bagus vs berantakan: desain dulu, generate kemudian. Ambil fitur sederhana โ€” "wishlist produk" โ€” dan tulis kontraknya di kertas/notes:

FITUR: Wishlist produk
RESOURCE: wishlist_items

GET    /v1/wishlist               โ†’ daftar wishlist user login   โ†’ 200
POST   /v1/wishlist               โ†’ tambah item {product_id}     โ†’ 201 | 422 | 409 (sudah ada)
DELETE /v1/wishlist/{product_id}  โ†’ hapus item                   โ†’ 204 | 404

ATURAN:
- Semua endpoint butuh auth (Bearer)
- User hanya melihat/mengubah wishlist MILIKNYA (anti-IDOR!)
- product_id harus exists di tabel products
- Duplikat โ†’ 409, bukan menambah baris kembar

Sekarang serahkan kontrak itu ke AI:

๐Ÿ’ก "Implementasikan kontrak API berikut di [framework Anda]. Patuhi persis status code dan aturannya, jangan menambah endpoint lain: [tempel kontrak]"

Bandingkan hasilnya dengan kontrak Anda baris per baris. Setiap penyimpangan = bahan revisi prompt.

Langkah 3 โ€” Tes seperti QA (15 menit)

Jangan hanya tes skenario sukses. Minimal 6 tes ini untuk endpoint POST di atas:

# Tes Ekspektasi
1 Tanpa header Authorization 401
2 Token valid + product_id valid 201 + item muncul di GET
3 product_id tidak ada di database 422
4 product_id dikirim sebagai string kosong 422
5 POST item yang sama dua kali Kedua: 409
6 DELETE product_id milik wishlist user LAIN 404 (bukan terhapus!)
# contoh tes #2
curl -i -X POST http://localhost:8000/v1/wishlist \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"product_id": 1}'

Kalau ada yang gagal โ†’ kembali ke AI dengan bukti: "Tes #5 gagal: request kedua mengembalikan 201 dan membuat baris duplikat. Perbaiki agar 409, dan tambahkan unique constraint di level database juga."

Langkah 4 โ€” Simpan artefaknya

Kontrak + tabel tes di atas adalah dokumentasi hidup fitur Anda. Simpan di repo (misal docs/api/wishlist.md). Fitur berikutnya: ulangi pola yang sama. Inilah loop inti vibe coding yang sehat: kontrak โ†’ generate โ†’ tes โ†’ revisi.


Rangkuman Bab

  • API = kontrak komunikasi; REST = gaya desain paling umum (resource + method).
  • Request punya method, URL, headers, body โ€” tahu di mana menaruh data (path/query/body).
  • Status code adalah bahasa universal hasil request; hafal pasangan 401/403 dan 400/422.
  • JSON punya jebakan: uang sebagai float, tanggal ambigu, angka sebagai string.
  • JWT bisa dibaca siapa saja โ€” jangan taruh data sensitif di dalamnya.
  • Idempotency menentukan operasi mana yang aman di-retry.
  • Semua orang bisa mengetes API dengan curl/Postman โ€” tidak perlu menunggu UI.

โ† Pengantar | Index | Lanjut: Database โ†’