Seluruh section ini membangun API yang menyenangkan untuk diprogram: kontrak JSON yang konsisten, validasi yang tegas, autentikasi yang aman, error yang berbahasa mesin. Tetapi tidak satu pun berguna bila konsumen tidak tahu kontraknya. Dokumentasi API adalah pintu masuk tim client — mereka perlu tahu endpoint mana yang tersedia, parameter apa saja yang diterima, bentuk response sukses, dan bentuk error yang harus diantisipasi. Chapter penutup ini merangkai praktik dokumentasi yang realistis: format standar OpenAPI, daftar endpoint dari route:list --json, kontrak yang dijaga feature test, sampai changelog per versi. Karena Course ini berjalan tanpa akses jaringan, contoh alat eksternal kita tampilkan sebagai potongan kode tanpa klaim eksekusi — bagian yang dijalankan benar-benar kita jalankan.

Konsumen Butuh Apa Saja #

Mari berdiri di posisi tim client yang akan memakai API kita. Empat pertanyaan harus terjawab oleh dokumentasi:

  • Endpoint dan operasi — method HTTP, path, dan kebutuhan autentikasi tiap operasi.
  • Parameter — path parameter, query parameter, body field, lengkap dengan tipe dan aturan validasinya.
  • Response sukses — bentuk JSON dan status code untuk setiap skenario berhasil.
  • Response error — bentuk 401, 403, 404, 409, 422, 429, dan 500 yang bisa diprogram.

Dokumentasi yang baik ditulis satu kali dan dijaga selamanya — itulah mengapa banyak tim menyimpannya berdampingan dengan kode, bukan di file Word yang terpisah tiga sprint dari kenyataan.

OpenAPI sebagai Format Standar #

OpenAPI (dulu bernama Swagger) adalah spesifikasi de facto untuk mendeskripsikan REST API dalam satu dokumen JSON atau YAML. Client generator, playground interaktif, dan validator bisa memakan dokumen ini. Cuplikan berikut menggambarkan endpoint show versi 1 kita dalam format OpenAPI 3.1 — ditampilkan apa adanya tanpa dieksekusi:

yaml
openapi: 3.1.0
info:
  title: Course API
  version: 1.0.0
paths:
  /api/v1/posts/{post}:
    get:
      summary: Detail satu post (deprecated)
      deprecated: true
      parameters:
        - name: post
          in: path
          required: true
          schema: { type: integer }
      responses:
        "200":
          description: Post ditemukan
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Post" }
        "404":
          description: Post tidak ditemukan (envelope error)
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Error" }
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code: { type: string }
            message: { type: string }

Perhatikan keselarasan alami dengan keputusan kita sepanjang section ini: field deprecated: true pada operasi, envelope {error: {code, message}} sebagai schema bersama, dan status code yang persis kita uji di feature test. Dokumen OpenAPI yang ditulis dengan disiplin adalah cermin langsung dari kontrak yang dijaga kode.

route:list –json sebagai Peta Endpoint #

Menulis daftar endpoint manual cepat basi; artisan bisa mengeluarkannya dalam JSON yang bisa diproses:

bash
php artisan route:list --path=api/v2 --json

Output yang Dihasilkan:

text
[
    {
        "domain": null,
        "method": "GET|HEAD",
        "uri": "api/v2/posts",
        "name": "v2.posts.index",
        "action": "App\\Http\\Controllers\\Api\\V2\\PostController@index",
        "middleware": ["api"],
        "path": null
    },
    {
        "domain": null,
        "method": "GET|HEAD",
        "uri": "api/v2/posts/{post}",
        "name": "v2.posts.show",
        "action": "App\\Http\\Controllers\\Api\\V2\\PostController@show",
        "middleware": ["api"],
        "path": null
    }
]

Untuk api/v1/posts yang lebih ramai, keluarannya juga memuat parameter middleware — termasuk MarkDeprecated:v1,2025-12-31 yang terpasang di show dan Authenticate:sanctum di update. Peta ini akurat karena dibaca langsung dari router, tetapi peta ini hanya tahu struktur endpoint — parameter query, bentuk response, dan contoh payload harus dirawat dari sumber lain.

Sumber Kebenaran Lain dan Tooling #

Kode kita sendiri menyimpan sebagian besar kebenaran kontrak. Resource class — dibahas tuntas di API Resource Classes — adalah definisi bentuk response yang selalu mutakhir karena dipakai setiap request. Feature test adalah kontrak yang dieksekusi: begitu bentuk response berubah, test merah. Ekosistem Laravel juga punya Scramble (composer require dedoc/scramble) — paket yang menghasilkan dokumen OpenAPI otomatis dengan membaca route, FormRequest, dan resource class tanpa anotasi manual, lalu menyajikannya sebagai playground interaktif di /docs/api yang ikut ter-update setiap kode berubah — pola yang cocok untuk API yang tumbuh cepat. Kekurangannya juga jujur diakui: generator mengambil bentuk dari kode, sehingga keputusan yang tidak tercermin di kode (misalnya kapan sebuah endpoint akan dihapus) tetap perlu ditulis manusia di changelog.

Kontrak yang Dieksekusi #

Praktik favorit kita: menjadikan feature test sebagai dokumentasi yang tidak bisa berbohong. Test berikut menegaskan seluruh kontrak publik endpoint posts — bentuk data v1 dan v2, struktur pagination, header deprecation, sampai envelope error 404:

php
<?php

// tests/Feature/ApiContractTest.php (cuplikan)

public function test_kontrak_show_v1(): void
{
    $budi = User::factory()->create(['name' => 'Budi', 'email' => '[email protected]']);
    $post = Post::factory()->create(['user_id' => $budi->id, 'title' => 'Post kontrak']);

    $this->getJson("/api/v1/posts/{$post->id}")
        ->assertOk()
        ->assertJsonStructure([
            'id', 'user_id', 'title', 'content', 'status',
            'published_at', 'created_at', 'updated_at',
        ])
        ->assertHeader('Deprecation', 'true')
        ->assertHeader('Sunset', 'Wed, 31 Dec 2025 23:59:59 GMT');
}

public function test_kontrak_index_v1_berpaginasi(): void
{
    $this->getJson('/api/v1/posts?per_page=2')
        ->assertOk()
        ->assertJsonStructure([
            'data' => [['id', 'judul', 'status', 'penulis', 'published_at']],
            'links' => ['first', 'last', 'prev', 'next'],
            'meta' => ['current_page', 'from', 'last_page', 'path', 'per_page', 'to', 'total'],
        ]);
}

Test class ini dijalankan utuh dalam empat test — dan assertion semacam ini adalah pola yang dibahas luas di dokumentasi http-tests :

Output yang Dihasilkan:

text
  PASS  Tests\Feature\ApiContractTest
  ✓  kontrak show v1                                                     0.16s
  ✓  kontrak show v2                                                     0.01s
  ✓  kontrak index v1 berpaginasi                                        0.02s
  ✓  kontrak error 404 memakai envelope                                  0.01s

  Tests:    4 passed (44 assertions)
  Duration: 0.27s

Empat puluh empat assertion adalah jumlah fakta kontrak yang dijaga mesin ini — siapa pun yang mengubah response tanpa sadar akan dibangunkan oleh test yang merah sebelum client yang marah.

Changelog per Versi #

Terakhir, konsumen butuh narasi perubahan yang manusiawi — apa yang berubah, kapan, dan apa yang harus dilakukan. File CHANGELOG.md di root proyek yang dijaga per rilis sudah menjadi konvensi yang mapan:

markdown
<!-- isi CHANGELOG.md, contoh display -->
## [2.0.0] - 2026-02-01
### Breaking
- `GET /api/v2/posts/{id}` mengganti field `content` menjadi `isi` dan
  menambah `ringkasan`; `user_id` tidak lagi ditampilkan.
### Deprecated
- `GET /api/v1/posts/{id}` ditandai deprecated; sunset 31 Desember 2025.

Dengan itu rangkaian dokumentasi kita lengkap: format standar OpenAPI untuk mesin, route:list --json untuk peta otomatis, resource class dan feature test sebagai sumber kebenaran yang dijaga kode, dan changelog untuk manusia. Section API Development pun tertutup — kita sudah berjalan dari konsep REST sampai API yang teruji kontraknya. Langkah alami berikutnya adalah memperdalam senjata autentikasi pilihan kita di section Laravel Sanctum , tempat token abilities dan SPA authentication dibedah sampai ke dalamnya.