02 โ REST API¶
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
GETyang mengubah data (misalGET /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
200bahkan 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:
/productsbukan/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_caseataucamelCase) 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.30000000000000004di banyak bahasa. Untuk uang, simpan sebagai integer satuan terkecil (Rp75.000 โ75000; $19.99 โ1999sen). - 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 headerX-RateLimit-RemainingdanRetry-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_idwajib & exists di tabel products,quantitywajib & minimal 1 - Bungkus pembuatan order + pengurangan stok dalam satu database transaction - Response201dengan data order;422bila validasi gagal atau stok kurang (sertakan detail per field);404bila produk tidak ditemukan - Format field responsesnake_case, tanggal ISO 8601 UTC, harga sebagai integer rupiah - Ikuti konvensi endpoint yang sudah ada di project (lihatroutes/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
404dan 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.