Aplikasi Laravel kita jarang berdiri sendiri. Frontend JavaScript, aplikasi mobile, dan layanan pihak ketiga membutuhkan cara berkomunikasi dengan aplikasi kita — dan cara paling umum hari ini adalah REST API. REST (Representational State Transfer) adalah gaya arsitektur yang memanfaatkan infrastruktur HTTP yang sudah ada: URL menamai data, method menentukan aksi, dan status code melaporkan hasil. Chapter ini membangun fondasi konseptual yang akan kita pakai di sepanjang Section API Development, jadi mari kita mulai dari prinsipnya sebelum menyentuh satu baris kode Laravel pun.

Resource Adalah Kata Benda, Bukan Kata Kerja #

Prinsip pertama REST: setiap endpoint menunjuk resource — entitas data seperti post, user, atau komentar. URL seharusnya menamai resource dengan kata benda, sedangkan aksi ditentukan oleh HTTP method. Gaya lama seperti /getPosts mencampurkan aksi ke dalam nama URL dan mengabaikan method GET yang sudah jelas berarti “ambil data”. REST memisahkan keduanya dengan tegas:

| Gaya lama (RPC-like) | Gaya REST | Aksi | | | | | | /getPosts | GET /posts | Daftar post | | /createPost | POST /posts | Buat post baru | | /updatePost?id=1 | PUT /posts/1 | Ubah post bernomor ID 1 | | /deletePost?id=1 | DELETE /posts/1 | Hapus post bernomor ID 1 |

Perhatikan polanya: identitas resource konsisten berada di /posts dan /posts/{id}, sementara method GET, POST, PUT, dan DELETE memberikan makna pada URL yang sama. Satu resource, banyak aksi.

HTTP Method dan Pemetaan CRUD #

HTTP method bukan sekadar dekorasi — setiap method membawa janji perilaku. Tabel berikut merangkum pemetaan method ke operasi CRUD beserta sifat pentingnya:

| Method | Operasi CRUD | Idempotent? | Catatan | | | | | | | GET | Read | Ya | Aman diulang, tidak mengubah data | | POST | Create | Tidak | Request berulang bisa membuat duplikat | | PUT | Update (menyeluruh) | Ya | Mengganti seluruh resource | | PATCH | Update (sebagian) | Tidak dijamin | Hanya mengubah field tertentu | | DELETE | Delete | Ya | Penghapusan kedua tetap “sudah terhapus” |

Idempotent berarti request yang dikirim berulang menghasilkan keadaan akhir yang sama. Sifat ini penting ketika jaringan tidak stabil dan client otomatis mengulang request — PUT /posts/1 yang terkirim dua kali tetap menghasilkan satu post dengan isi yang sama, sedangkan POST /posts yang terkirim dua kali bisa membuat dua post.

Status Code sebagai Bahasa Hasil #

Response API tidak cukup hanya membawa data — baris pertamanya harus jujur melaporkan hasil operasi. HTTP membagi status code menjadi lima keluarga:

| Keluarga | Arti | Contoh | | | | | | 1xx | Informatif | 101 Switching Protocols | | 2xx | Sukses | 200 OK, 201 Created, 204 No Content | | 3xx | Redirect | 301 Moved Permanently | | 4xx | Kesalahan client | 400, 401, 403, 404, 405, 422, 429 | | 5xx | Kesalahan server | 500 Internal Server Error |

Kode yang paling sering kita pakai sehari-hari: 200 untuk GET yang sukses, 201 setelah resource berhasil dibuat, 204 untuk DELETE yang sukses tanpa body, 404 saat resource tidak ada, 405 saat method tidak didukung endpoint, dan 422 saat validasi gagal. Client yang membaca status code dengan benar tidak perlu menebak-menebak isi body.

Stateless: Setiap Request Berdiri Sendiri #

REST mensyaratkan server stateless — server tidak menyimpan ingatan percakapan antar request. Setiap request harus membawa sendiri seluruh informasi yang dibutuhkan: identitas pemanggil (misalnya token di header Authorization), parameter, dan data yang dikirim. Kontrasnya dengan aplikasi web tradisional yang mengandalkan session di server untuk mengenali pengguna antar halaman. Akibat statelessness, setiap request bisa dilayani oleh server mana pun dalam kluster — kondisi yang memudahkan penskalaan horizontal.

API Routes vs Web Routes di Laravel #

Laravel menyediakan dua dunia route yang terpisah karena perbedaan mendasar ini:

| Aspek | routes/web.php | routes/api.php | | | | | | Audiens | Browser | Aplikasi client (JS, mobile, pihak ketiga) | | Output utama | HTML + session | JSON tanpa keadaan | | Autentikasi | Cookie + session | Token (misalnya Bearer token) | | Middleware group | web (session, CSRF) | api (stateless) |

Route API secara otomatis mendapat prefix /api — kita bedah mekanismenya di chapter API Routing . Karena tidak ada session, tidak ada pula proteksi CSRF dan tidak ada cookie login; identitas dikirim ulang di setiap request lewat header.

REST dalam Praktik #

Teori di atas akan lebih melekat jika kita lihat sendiri bagaimana server merespons. Kita definisikan endpoint sederhana untuk resource posts:

php
<?php

// routes/api.php

use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('/ping', fn (): array => ['message' => 'pong']);

Route::get('/posts', fn () => Post::all(['id', 'title']));

Route::post('/posts', function (Request $request) {
    $post = Post::create($request->validate([
        'title' => 'required|string|max:100',
        'content' => 'required|string',
        'user_id' => 'required|integer|exists:users,id',
    ]));

    return response()->json($post, 201);
});

Route::get('/posts/{post}', fn (Post $post) => $post);

Route::delete('/posts/{post}', function (Post $post) {
    $post->delete();

    return response()->noContent();
});

Lalu kita tembak delapan request dari runner CLI dan mencatat status serta body-nya:

php
<?php

// uji-rest.php — jalankan: php uji-rest.php <path-proyek-laravel>
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

$dir = $argv[1];
require $dir.'/vendor/autoload.php';
$app = require $dir.'/bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

$kirim = function (string $method, string $uri, ?array $json = null) use ($kernel) {
    $server = ['HTTP_ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json'];
    $request = Request::create('http://localhost'.$uri, $method, [], [], [], $server,
        $json ? json_encode($json) : null);
    $response = $kernel->handle($request);

    return sprintf('%-6s %-16s → HTTP %d  %s', $method, $uri,
        $response->getStatusCode(), $response->getContent());
};

echo $kirim('GET', '/api/ping'), PHP_EOL;
echo $kirim('GET', '/api/posts'), PHP_EOL;
echo $kirim('GET', '/api/posts/1'), PHP_EOL;
echo $kirim('POST', '/api/posts', ['title' => 'Post Baru', 'content' => 'Isi baru.', 'user_id' => 1]), PHP_EOL;
echo $kirim('DELETE', '/api/posts/1'), PHP_EOL;
echo $kirim('GET', '/api/posts/1'), PHP_EOL;
echo $kirim('PUT', '/api/posts'), PHP_EOL;
echo $kirim('GET', '/api/getPosts'), PHP_EOL;

Output yang Dihasilkan:

text
GET    /api/ping        → HTTP 200  {"message":"pong"}
GET    /api/posts       → HTTP 200  [{"id":1,"title":"Belajar REST API"}]
GET    /api/posts/1     → HTTP 200  {"id":1,"user_id":1,"title":"Belajar REST API","content":"Konten post pertama.","created_at":"2026-01-02T09:00:00.000000Z","updated_at":"2026-01-02T09:00:00.000000Z"}
POST   /api/posts       → HTTP 201  {"title":"Post Baru","content":"Isi baru.","user_id":1,"updated_at":"2026-01-02T09:00:00.000000Z","created_at":"2026-01-02T09:00:00.000000Z","id":2}
DELETE /api/posts/1     → HTTP 204
GET    /api/posts/1     → HTTP 404  {
    "message": "No query results for model [App\\Models\\Post] 1"
}
PUT    /api/posts       → HTTP 405  {
    "message": "The PUT method is not supported for route api/posts. Supported methods: GET, HEAD, POST."
}
GET    /api/getPosts    → HTTP 404  {
    "message": "The route api/getPosts could not be found."
}

Mari kita baca hasilnya baris demi baris:

  1. GET /api/posts → 200: method dan resource cocok, daftar post dikembalikan sebagai array JSON.
  2. POST /api/posts → 201: resource baru lahir dengan ID 2, tepat seperti janji status Created.
  3. DELETE /api/posts/1 → 204: penghapusan sukses dan body sengaja kosong — tidak ada lagi yang perlu dilaporkan.
  4. GET /api/posts/1 setelah dihapus → 404: resource sudah tidak ada, server jujur mengatakannya.
  5. PUT /api/posts → 405: endpoint collection hanya menerima GET dan POST, jadi Laravel menolak method PUT dan menyebutkan method yang didukung.
  6. GET /api/getPosts → 404: URL gaya lama memang tidak pernah kita definisikan — noun-only menang.

Prinsip REST — resource berbenda, method bermakna, status code jujur, dan request stateless — kini menjadi kompas kita. Langkah berikutnya adalah mengimplementasikannya di Laravel secara sistematis, dimulai dari cara framework mendaftarkan route API di API Routing .