Request & Response — API

Memahami struktur request dan response adalah kunci membangun API yang baik. Status codes yang wajib diketahui: Code Nama Kapan Dipakai 200 OK Request…

Setiap obrolan dengan API terdiri dari dua pesan: request dari client dan response dari server. Bentuk keduanya sama: baris pertama, header, baris kosong, lalu body. Bayangin kirim paket lewat kurir. Label di luar kotak (header) bilang isinya apa dan mau ke mana, kotaknya berisi barangnya (body), dan kurir pulang membawa tanda terima dengan satu cap (status code): diterima, alamat gak ketemu, atau ditolak karena kemasannya salah.

🧪 Tebakan cepat: client mengirim body JSON yang benar, tapi lupa header Content-Type: application/json. Apa yang terjadi di server? Tebak dulu, jawabannya ada di bagian "Header: label di luar kotak".

Isi sebuah request

Admin Toko Buku menambah buku baru:

POST /books HTTP/1.1
Host: api.tokobuku.test
Content-Type: application/json
Accept: application/json

{"title": "Ronggeng Dukuh Paruk", "author_id": 4, "price": 95000, "stock": 8}

Data bisa ikut di empat tempat, dan tiap tempat punya tugas:

Tempat Contoh Tugasnya
path /books/4 menunjuk benda yang mana
query ?author_id=2 pilihan untuk daftar
header Content-Type: application/json keterangan tentang request-nya
body {"title": "..."} data yang dikirim (POST, PUT, PATCH)

Header: label di luar kotak

Server membaca Content-Type dulu sebelum membuka body. Tanpa application/json, server gak tahu body-nya JSON, jadi body-nya gak di-parse. Itu jawaban tebakannya. Di Express, express.json() cuma membaca body yang Content-Type-nya JSON, jadi req.body kosong dan validasi bilang title gak ada. Server yang lebih ketat langsung menjawab 415 Unsupported Media Type. Hasilnya sama: data yang kamu kirim gak terbaca.

Jebakannya, fetch dengan body teks dan tanpa header mengirim Content-Type: text/plain;charset=UTF-8. Jadi tulis header-nya sendiri:

fetch("https://api.tokobuku.test/books", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ title: "Ronggeng Dukuh Paruk", author_id: 4, price: 95000, stock: 8 }),
});

Status code: jawaban dalam tiga angka

Angka pertama menyebut kelompoknya: 2xx berhasil, 3xx pindah alamat (redirect), 4xx salahnya di request (client), 5xx salahnya di server.

Status Nama Kapan, di API Toko Buku
200 OK GET /books/1 berhasil
201 Created POST /books membuat buku baru
204 No Content DELETE /books/2 berhasil, tanpa body
400 Bad Request body bukan JSON yang sah, atau field wajib gak ada
404 Not Found GET /books/99
405 Method Not Allowed PUT /books
415 Unsupported Media Type body dikirim tanpa Content-Type: application/json
422 Unprocessable Content JSON-nya terbaca, tapi nilainya gak masuk akal, misalnya "price": -5000
500 Internal Server Error bug di server

200 artinya berhasil, 404 artinya Not Found: yang diminta gak ada. Batas 400 dan 422 gak dipatok mati. Banyak API memakai 400 untuk semua input yang salah, sebagian (Laravel, misalnya) memakai 422 untuk semua yang gagal validasi. Toko Buku memakai 400 untuk body yang gak bisa dibaca atau kehilangan field wajib, dan 422 untuk nilai yang gak masuk akal. Pilih satu aturan, lalu konsisten.

Bentuk body yang konsisten

Client paling senang kalau semua endpoint menjawab dengan bentuk yang sama. Di Toko Buku, jawaban berhasil berisi datanya langsung, dan jawaban gagal selalu berbentuk {"error": "..."}. Banyak API lain membungkus jawaban berhasil jadi {"data": ..., "message": "..."}. Latihan ini memakai bentuk bungkus itu. Bentuk mana pun boleh, asal satu bentuk dipakai di semua endpoint.

Latihan: POST /register

Ini endpoint tambah buku di Toko Buku:

app.post("/books", (req, res) => {
  const { title, price } = req.body;
  if (!title) {
    return res.status(400).json({ error: "title is required" });
  }
  res.status(201).json({ id: 4, title, price });
});

Latihannya sama bentuknya: endpoint POST /register, field name dan email. Tanpa name, jawab 400 dengan {"error": "Name is required"}. Kalau lengkap, jawab 201 dengan {"data": {"name": ..., "email": ...}, "message": "Registered!"}.

⚠️ Jebakan yang sering ketemu

TL;DR: Request = baris pertama (method, path), header, baris kosong, body; response = status line, header, body. Path menunjuk benda, query mengatur daftar, header memberi keterangan, body membawa data. Content-Type: application/json wajib saat mengirim body JSON; tanpa itu server gak mem-parse body (atau menjawab 415), dan fetch tanpa header mengirim text/plain. Status: 2xx berhasil (200 OK, 201 Created, 204 No Content), 4xx salah di request (400 Bad Request, 404 Not Found, 405, 415, 422), 5xx salah di server. Kirim error dengan res.status(...) lalu return, dan pakai satu bentuk body di semua endpoint.

Yang akan kamu pelajari