Beranda/Artikel/Desain API yang Gak Bikin Konsumen (Termasuk Tim Sendiri) Frustrasi

Collaborative Flowchart in a Modern WorkspaceBackend

Desain API yang Gak Bikin Konsumen (Termasuk Tim Sendiri) Frustrasi

14 Menit Baca 14 Agustus 2026Ditulis oleh Sukses Corp Tech
Sumber:Sukses Corp Tech
32 0

API yang berhasil mengembalikan response 200 belum tentu merupakan API yang enak dipakai. Banyak integrasi terasa sulit bukan karena backend-nya tidak mampu memproses request, tetapi karena konsumen API harus menebak pola endpoint, arti field, bentuk error, aturan pagination, atau perubahan kontrak yang tidak pernah dijelaskan dengan jelas.

Dalam konteks software modern, application programming interface (API) adalah kontrak komunikasi antara satu komponen software dan komponen lain. Konsumennya bisa aplikasi mobile, frontend web, service internal, partner eksternal, data pipeline, automation worker, atau bahkan tim backend lain di perusahaan yang sama.

Karena itu, desain API seharusnya tidak hanya dinilai dari perspektif pembuatnya.

API yang terlihat “rapi” dari sisi server bisa tetap membuat consumer frustrasi jika setiap endpoint memakai pola berbeda, status code tidak konsisten, error message minim konteks, atau dokumentasi tertinggal dari implementasi.

Artikel sebelumnya tentang code review yang efektif membahas pentingnya menjaga kualitas perubahan sebelum masuk ke codebase. Prinsip yang sama berlaku pada API: kualitas interface perlu dijaga karena begitu kontrak digunakan consumer lain, perubahan kecil pun bisa punya efek yang jauh lebih besar.

Apa yang Membuat Desain API Nyaman Digunakan?

Desain API yang nyaman digunakan membuat pola interaksinya dapat diprediksi. Konsumen seharusnya bisa memahami cara membaca resource, membuat data, memperbarui state, menangani error, dan memproses response tanpa harus membuka source code backend atau bertanya ke pembuat endpoint setiap kali ada integrasi baru.

Predictability adalah salah satu kualitas terpenting.

Jika konsumen sudah memahami satu endpoint, idealnya pengetahuan tersebut bisa dipakai untuk memahami endpoint lain.

Misalnya, kalau resource customer menggunakan:

GET /customers/{id}

maka konsumen akan lebih mudah menebak bahwa daftar order mungkin tersedia melalui:

GET /orders

dan detail order melalui:

GET /orders/{id}

Sebaliknya, API seperti:

GET /getCustomer POST /orders/fetch POST /update-user GET /order/detail?id=123

mungkin tetap berfungsi, tetapi beban kognitif konsumen meningkat karena setiap endpoint seperti punya aturan sendiri.

Desain API yang baik tidak berarti harus mengikuti satu gaya secara dogmatis. REST, RPC, GraphQL, event-driven interface, dan pendekatan lain punya trade-off masing-masing. Yang paling penting adalah kontraknya konsisten dengan model komunikasi yang dipilih.

Mengapa Konsistensi Penamaan Sangat Penting dalam Desain API?

Konsistensi penamaan mengurangi jumlah keputusan kecil yang harus dibuat konsumen saat melakukan integrasi. Endpoint, parameter, field response, enum, dan struktur resource sebaiknya mengikuti aturan yang sama di seluruh API.

Misalnya, tim perlu menentukan apakah menggunakan:

user_id

atau:

userId

Keduanya valid. Masalah muncul ketika satu endpoint mengembalikan user_id, endpoint lain userId, lalu endpoint ketiga memakai customerID untuk konsep yang serupa.

Hal yang sama berlaku untuk naming resource.

Kalau API memilih bentuk plural:

/users /orders /products

usahakan jangan tiba-tiba menggunakan /invoice untuk collection yang setara tanpa alasan jelas.

Konsistensi juga mencakup konsep waktu.

Apakah timestamp memakai UTC? Apakah field bernama createdAt, created_at, atau createdDate? Format tanggal seperti apa yang dijanjikan? Apakah nullable field dikirim sebagai null atau dihilangkan?

Keputusan-keputusan ini terlihat kecil ketika hanya ada tiga endpoint. Ketika API berkembang menjadi puluhan atau ratusan endpoint, inkonsistensi kecil akan berubah menjadi biaya integrasi yang nyata.

Dokumentasikan convention tersebut di API style guide atau engineering guideline agar reviewer tidak perlu memperdebatkan hal yang sama berulang kali.

Bagaimana Memilih Endpoint dan HTTP Method yang Tepat?

Untuk API berbasis HTTP, endpoint sebaiknya menggambarkan resource atau domain yang diakses, sementara HTTP method menggambarkan operasi terhadap resource tersebut.

RFC 9110 mendefinisikan semantics untuk method HTTP seperti GET, POST, PUT, dan DELETE. Mengikuti semantics tersebut membantu client, proxy, cache, library, dan developer memahami perilaku request tanpa aturan tambahan yang tidak perlu.

Contoh yang mudah diprediksi:

GET /orders/123

untuk mengambil order.

POST /orders

untuk membuat order baru.

PUT /orders/123

untuk mengganti representasi resource sesuai kontrak yang ditetapkan.

DELETE /orders/123

untuk menghapus resource jika domain memang memperbolehkannya.

Bukan berarti setiap business action harus dipaksa menjadi CRUD sederhana.

Ada domain action yang memang lebih jelas jika diekspresikan eksplisit. Misalnya:

POST /orders/123/cancel

bisa lebih mudah dipahami daripada mencoba menyamarkan proses pembatalan sebagai update field biasa jika cancellation memiliki aturan bisnis, side effect, dan audit trail yang kompleks.

Yang penting adalah semantics endpoint dapat dipahami dan digunakan secara konsisten.

Hindari penggunaan GET untuk operasi yang mengubah state. Selain membingungkan developer, perilaku tersebut berlawanan dengan semantics safe method pada HTTP dan bisa menimbulkan efek tidak terduga jika URL diakses oleh crawler, prefetcher, atau komponen intermediary.

Seperti Apa Response API yang Konsisten?

Response API yang konsisten membuat consumer lebih mudah membangun parsing, error handling, observability, dan type definition. Struktur response tidak harus identik untuk semua endpoint, tetapi pola dasarnya perlu jelas.

Misalnya, untuk single resource:

{
  "id": "ord_123",
  "status": "paid",
  "total": 275000,
  "currency": "IDR"
}

Untuk collection:

{
  "data": [
    {
      "id": "ord_123",
      "status": "paid"
    },
    {
      "id": "ord_124",
      "status": "pending"
    }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6Im9yZF8xMjQifQ"
  }
}

Tidak ada satu bentuk wrapper yang wajib dipakai semua API.

Sebagian tim selalu menggunakan data, sebagian mengembalikan resource langsung. Keduanya bisa bekerja.

Pertanyaan yang lebih penting adalah: apakah bentuk response predictable dan terdokumentasi?

Consumer seharusnya tidak perlu menangani satu endpoint dengan pola:

{ "data": ... }

endpoint lain:

{ "result": ... }

dan endpoint berikutnya:

{ "payload": ... }

tanpa alasan domain yang jelas.

Konsistensi sangat berharga bagi typed client. Ketika schema API digunakan untuk menghasilkan SDK atau type definition, contract yang stabil mengurangi banyak pekerjaan manual.

Mengapa Error Message Tidak Boleh Cuma Berisi Status Code?

HTTP status code memberi kategori umum tentang hasil request, tetapi sering belum cukup untuk membantu consumer memperbaiki masalah. Error response yang baik perlu memberi informasi yang dapat ditindaklanjuti tanpa membocorkan detail sensitif dari sistem internal.

Bandingkan response berikut:

{
  "error": "Bad Request"
}

dengan:

{
  "error": {
    "code": "INVALID_ORDER_STATUS",
    "message": "Order berstatus shipped tidak dapat dibatalkan.",
    "requestId": "req_01JXYZ..."
  }
}

Response kedua jauh lebih berguna.

Status HTTP, misalnya 400 atau 409, membantu client memahami kategori masalah. Error code yang stabil membantu aplikasi mengambil tindakan programmatic. Pesan yang jelas membantu developer melakukan debugging. requestId membantu tim backend menelusuri log terkait.

Untuk validation error, struktur bisa dibuat lebih spesifik:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request tidak valid.",
    "fields": [
      {
        "field": "email",
        "reason": "invalid_format"
      }
    ]
  }
}

Yang perlu dihindari adalah membocorkan stack trace, query database, path server, credential, atau informasi internal lain ke consumer.

Error message harus informatif, bukan invasif.

Bagaimana Menggunakan HTTP Status Code Secara Konsisten?

Status code sebaiknya dipakai sesuai semantics-nya sehingga konsumen tidak harus menebak apakah request sukses atau gagal hanya dari body response.

Beberapa pola yang umum:

  • 200 OK untuk request yang berhasil dan mengembalikan representation;
  • 201 Created ketika resource baru berhasil dibuat;
  • 204 No Content ketika request berhasil tanpa response body;
  • 400 Bad Request untuk request yang secara umum tidak valid;
  • 401 Unauthorized ketika authentication diperlukan atau gagal;
  • 403 Forbidden ketika identity diketahui tetapi tidak punya permission;
  • 404 Not Found ketika resource tidak ditemukan;
  • 409 Conflict ketika request berbenturan dengan current state;
  • 422 Unprocessable Content untuk request yang formatnya dapat dipahami tetapi tidak dapat diproses sesuai semantics tertentu;
  • 429 Too Many Requests untuk rate limiting;
  • status 5xx untuk kegagalan di sisi server.

Daftar tersebut bukan aturan business logic universal. Yang paling penting adalah mapping tetap konsisten dan didokumentasikan.

Jangan membungkus semua kegagalan sebagai 200 OK dengan payload seperti:

{
  "success": false,
  "error": "not found"
}

Pola tersebut membuat client, monitoring, gateway, dan observability tool kehilangan banyak informasi yang sebenarnya sudah disediakan HTTP.

Mengapa Dokumentasi API Bukan Fitur Tambahan?

Dokumentasi adalah bagian dari contract API karena consumer perlu mengetahui behavior yang tidak selalu terlihat dari endpoint name atau schema response.

Dokumentasi minimal sebaiknya menjelaskan:

  • authentication;
  • base URL atau environment;
  • endpoint dan method;
  • request parameter;
  • request body;
  • response schema;
  • status code;
  • error format;
  • pagination;
  • rate limit jika ada;
  • contoh request dan response;
  • aturan versioning;
  • deprecation policy.

Dokumentasi yang bagus juga perlu menunjukkan constraint.

Misalnya, field status bukan sekadar string jika sebenarnya hanya menerima draft, paid, dan cancelled. Parameter limit bukan integer bebas jika maksimum yang diterima 100.

OpenAPI Specification dapat membantu mendeskripsikan HTTP API dalam format machine-readable. Schema tersebut dapat digunakan untuk dokumentasi, validation, testing, client generation, atau tooling lain.

Tetapi memakai OpenAPI tidak otomatis membuat dokumentasi bagus.

Schema tetap harus akurat dan selalu sinkron dengan implementasi. Dokumentasi yang lengkap tetapi sudah tertinggal dua versi justru membuat consumer lebih frustrasi daripada dokumentasi singkat yang benar.

Bagaimana Mendesain Pagination agar Tidak Menyulitkan Consumer?

Endpoint collection perlu punya strategi pagination sebelum volume data membesar. Mengembalikan semua record sekaligus mungkin terasa praktis pada tahap awal, tetapi cepat menjadi masalah ketika dataset tumbuh.

Dua pendekatan yang sering digunakan adalah offset-based dan cursor-based pagination.

Offset-based:

GET /orders?page=3&limit=20

atau:

GET /orders?offset=40&limit=20

Pendekatan ini mudah dipahami dan cocok untuk banyak dashboard atau dataset relatif stabil.

Cursor-based:

GET /orders?cursor=abc123&limit=20

lebih cocok untuk feed atau dataset yang sering berubah karena consumer melanjutkan dari posisi tertentu alih-alih menghitung offset.

Tidak ada satu metode yang selalu terbaik.

Yang penting consumer tahu:

  • parameter apa yang didukung;
  • default page size;
  • maksimum page size;
  • cara mengetahui masih ada data berikutnya;
  • apakah ordering stabil;
  • apa yang terjadi jika data berubah saat pagination berlangsung.

Pagination juga harus memiliki ordering yang deterministik. Menggunakan cursor tanpa sort yang stabil dapat menghasilkan item terlewat atau terbaca dua kali.

Bagaimana Filter, Sort, dan Search Sebaiknya Dirancang?

Filter dan sorting perlu mengikuti pola yang mudah diprediksi agar endpoint collection tidak berubah menjadi kumpulan parameter acak.

Contoh:

GET /orders?status=paid&sort=-createdAt

bisa berarti mengambil order berstatus paid dan mengurutkannya berdasarkan createdAt descending.

Kalau API mendukung filtering kompleks, dokumentasikan operator yang tersedia. Jangan membuat consumer menebak apakah range tanggal menggunakan:

createdFrom created_to fromDate start

pada endpoint yang berbeda.

Search juga perlu dibedakan dari filter.

Filter biasanya bersifat lebih deterministik berdasarkan field tertentu, sedangkan search bisa melakukan text matching atau relevancy scoring.

Kontrak yang eksplisit membantu consumer memahami apakah hasil pencarian memiliki ordering tertentu dan apakah exact match dijamin.

Mengapa Idempotency Penting untuk Operasi yang Bisa Diulang?

Network tidak selalu stabil. Consumer dapat mengirim request lalu kehilangan koneksi sebelum menerima response. Dalam kondisi itu, client perlu menentukan apakah request aman untuk dicoba lagi.

RFC 9110 menyebut PUT, DELETE, dan safe methods sebagai idempotent berdasarkan intended effect-nya. Artinya, mengirim request identik berkali-kali seharusnya memiliki intended effect yang sama seperti mengirimnya sekali.

POST secara umum tidak diasumsikan idempotent.

Untuk operasi sensitif seperti membuat pembayaran atau transaksi, retry tanpa perlindungan dapat menyebabkan duplikasi.

Salah satu pola yang dapat digunakan adalah idempotency key.

Contohnya:

Idempotency-Key: 6c701b4e-...

Server menyimpan hubungan antara key dan hasil operasi untuk periode tertentu. Jika request identik dikirim ulang dengan key yang sama, server dapat mengembalikan hasil yang sesuai tanpa membuat operasi bisnis baru.

Implementasinya perlu dirancang hati-hati, termasuk scope key, expiry, payload mismatch, persistence, dan concurrency. Jangan sekadar menambahkan header tanpa semantics yang terdokumentasi.

Bagaimana Mengelola Perubahan API Tanpa Merusak Consumer?

API yang sudah digunakan tim lain adalah dependency. Perubahan contract harus diperlakukan seperti perubahan public interface meskipun konsumennya hanya tim internal.

Breaking change bisa berupa:

  • menghapus field;
  • mengganti tipe field;
  • mengganti nama field;
  • mengubah semantics nilai;
  • menambah field required pada request;
  • mengubah status code;
  • mengubah authentication flow;
  • mengubah default ordering;
  • mempersempit validation secara drastis.

Sebaliknya, menambahkan optional field pada response sering lebih mudah dibuat backward compatible, selama consumer tidak menggunakan parser yang menolak field tambahan.

Sebelum membuat version baru, pertimbangkan apakah perubahan memang benar-benar breaking.

Versioning adalah alat, bukan tujuan.

API /v1/ dan /v2/ tetap sulit dikelola jika tidak ada migration plan, deprecation policy, ownership, dan telemetry tentang consumer yang masih menggunakan versi lama.

Untuk API internal, komunikasi perubahan tetap penting. Jangan berasumsi bahwa karena consumer duduk di kantor atau Slack workspace yang sama, perubahan bisa dilakukan tanpa contract management.

Apa Peran Security dalam Desain API?

Security seharusnya menjadi bagian dari contract sejak awal, bukan tambahan setelah endpoint selesai.

Consumer perlu memahami bagaimana authentication dilakukan, scope permission, dan data apa yang boleh diakses.

Prinsip pentingnya adalah authorization harus divalidasi di server untuk setiap resource yang relevan. Memiliki token valid tidak otomatis berarti client boleh mengakses semua object.

Contoh sederhana:

GET /orders/123

tidak boleh hanya memeriksa apakah pengguna sudah login. Server juga perlu memastikan pengguna tersebut memang memiliki hak melihat order 123.

API juga perlu memiliki validasi input, rate limiting sesuai kebutuhan, secret management yang benar, encrypted transport melalui HTTPS, logging yang tidak menyimpan credential secara sembarangan, serta pembatasan informasi pada error message.

Jangan mengandalkan consumer untuk melakukan enforcement keamanan.

Frontend bisa menyembunyikan tombol, tetapi backend tetap harus memvalidasi permission.

Bagaimana Membuat API Lebih Mudah Di-debug?

API yang enak dipakai juga enak ditelusuri ketika ada masalah.

Salah satu pola yang sangat membantu adalah correlation atau request ID. Setiap request memiliki identifier yang bisa diteruskan melalui service terkait dan dicatat pada log.

Ketika consumer melaporkan:

“Request kami gagal sekitar jam 14.30.”

tim backend jauh lebih mudah mencari masalah jika consumer dapat memberikan:

requestId = req_01JXYZ...

daripada harus menebak berdasarkan timestamp, user, endpoint, dan payload.

Observability yang baik juga membutuhkan metric dan tracing sesuai kompleksitas sistem.

Namun jangan melempar detail observability internal ke response tanpa kontrol. Consumer hanya butuh identifier yang aman dan informasi yang cukup untuk mengambil langkah berikutnya.

Contoh API yang Secara Teknis Berfungsi tetapi Sulit Digunakan

Bayangkan sebuah API order internal tumbuh selama dua tahun tanpa style guide.

Membuat order:

POST /createOrder

Mengambil detail:

GET /orders?id=123

Membatalkan:

GET /order/cancel/123

Mencari order:

POST /searchOrder

Sebagian endpoint menggunakan camelCase, sebagian snake_case. Error validation selalu 500. Timestamp kadang local time, kadang UTC. Dokumentasi terakhir diperbarui enam bulan lalu.

Secara teknis, semuanya bisa berfungsi.

Tetapi setiap integrator baru harus belajar banyak pengecualian.

Sekarang bandingkan dengan contract yang lebih konsisten:

POST /orders GET /orders/{id} POST /orders/{id}/cancel GET /orders?status=paid

Response memakai naming convention yang sama, timestamp punya format yang jelas, error memiliki code stabil, dan dokumentasi berasal dari schema yang diperbarui bersama perubahan implementation.

Backend tidak otomatis menjadi lebih canggih.

Yang berubah adalah developer experience.

Itulah mengapa desain API bukan kosmetik. Ia memengaruhi kecepatan integrasi, jumlah pertanyaan antar tim, kemungkinan salah implementasi, dan biaya maintenance jangka panjang.

Checklist Singkat Sebelum Endpoint Dianggap Siap

Sebelum endpoint baru dianggap selesai, tim dapat memeriksa beberapa pertanyaan berikut:

  1. Apakah nama resource dan field konsisten dengan API existing?
  2. Apakah HTTP method sesuai dengan semantics operasinya?
  3. Apakah success response konsisten dan mudah diparse?
  4. Apakah error memiliki status, code, dan pesan yang actionable?
  5. Apakah validation rule terdokumentasi?
  6. Apakah authentication dan authorization sudah diuji?
  7. Apakah behavior retry dan idempotency sudah jelas jika relevan?
  8. Apakah pagination dibutuhkan untuk collection?
  9. Apakah perubahan ini backward compatible?
  10. Apakah dokumentasi dan contoh request-response ikut diperbarui?
  11. Apakah request dapat ditelusuri melalui log atau request ID?
  12. Apakah automated test mencakup happy path dan failure path penting?

Checklist tidak menggantikan design review. Tetapi ia membantu mencegah pola masalah yang sama terulang.

FAQ tentang Desain API

Apakah semua API sebaiknya menggunakan REST?

Tidak. REST cocok untuk banyak API berbasis resource, tetapi RPC, GraphQL, event-driven architecture, gRPC, atau pendekatan lain bisa lebih sesuai untuk kebutuhan tertentu. Pilihan sebaiknya berdasarkan pola komunikasi, consumer, latency, evolusi schema, dan operasional sistem.

Apakah endpoint harus selalu memakai noun dan tidak boleh verb?

Tidak harus secara absolut. Resource-oriented endpoint biasanya lebih mudah diprediksi dengan noun, tetapi domain action seperti cancel, approve, atau retry kadang lebih jelas ditampilkan secara eksplisit. Jangan memaksakan CRUD jika justru membuat semantics bisnis menjadi kabur.

Haruskah response selalu memakai wrapper data?

Tidak. Mengembalikan resource langsung maupun melalui wrapper sama-sama valid. Yang lebih penting adalah konsistensi, kemampuan evolusi contract, kebutuhan metadata, serta kemudahan consumer.

Kapan API perlu versioning?

Versioning dibutuhkan ketika perubahan contract yang breaking tidak dapat dilakukan secara backward compatible dan consumer memerlukan masa migrasi. Jangan membuat versi baru untuk setiap perubahan kecil yang sebenarnya bisa ditambahkan secara kompatibel.

Apakah API internal perlu dokumentasi lengkap?

Ya, meskipun level detailnya dapat disesuaikan. Tim internal tetap merupakan consumer. Tanpa dokumentasi, knowledge hanya berpindah melalui chat dan ingatan developer, sehingga onboarding, debugging, dan pergantian ownership menjadi lebih mahal.

Apakah OpenAPI otomatis menyelesaikan masalah dokumentasi?

Tidak. OpenAPI membantu membuat contract lebih machine-readable dan dapat mendukung documentation tooling, validation, atau client generation. Tetapi schema tetap harus akurat, lengkap, dan diperbarui bersamaan dengan implementasi.

Kesimpulan

Desain API yang baik bukan tentang membuat endpoint terlihat elegan dari sisi backend. Ukurannya adalah seberapa mudah consumer dapat memahami, menggunakan, menangani kegagalan, dan mengikuti perubahan contract tanpa banyak tebakan.

Mulailah dari konsistensi penamaan. Gunakan HTTP semantics secara masuk akal. Buat response dan error predictable. Dokumentasikan constraint, bukan hanya endpoint. Rancang pagination dan filtering sebelum dataset membesar. Pikirkan idempotency untuk operasi yang rawan retry. Jaga backward compatibility dan security sebagai bagian dari desain, bukan pekerjaan tambahan di akhir.

API yang nyaman digunakan akan mengurangi trial and error, mempercepat integrasi, dan menurunkan biaya komunikasi antar tim.

Dan konsumen yang paling sering merasakan manfaatnya kadang bukan partner eksternal atau pelanggan. Bisa jadi developer di tim sendiri yang enam bulan kemudian harus menggunakan endpoint yang kamu buat hari ini.

Jika tim kamu sedang merancang kontrak API, integrasi antar-service, atau standar backend lintas aplikasi, kamu bisa diskusikan kebutuhan teknologi bisnis kamu dengan tim Sukses Corp Tech untuk membahas struktur yang sesuai dengan sistem dan pola integrasi yang digunakan.

Be part of a team that grows brands and people.

Start your next chapter with Sukses Career. Build your career in a company that values growth, collaboration, and meaningful impact.

Explore Jobs →
Share
← Previous ArticleCode Review yang Efektif: Bukan Sekadar Cari KesalahanNext Article →Kenapa SEO Teknis Sering Diabaikan Padahal Krusial

Comments

Memuat komentar...

Artikel Terkait