Langsung ke konten utama
Contoh payload di halaman ini disederhanakan supaya mudah dibaca. Beberapa route juga menambahkan header rate limit seperti X-RateLimit-Limit, X-RateLimit-Remaining, dan X-RateLimit-Reset.

Ringkasan endpoint

KelompokEndpoint utama
PublicPOST /api/contact, POST /api/waitlist, GET /api/health
User loginPOST /api/payments, POST /api/subscription, POST /api/profile, POST /api/profile/avatar
AdminPOST /api/admin/users/role
AIPOST /api/ai/chat, POST /api/ai/generate
Provider callbackPOST /api/webhooks/midtrans, POST /api/webhooks/doku

Public endpoint

PropertiNilai
AuthTidak perlu login
Feature gateContact feature harus aktif
Rate limit5 request per jam per IP
TujuanMengirim pesan dari form kontak via Resend
Request body:
{
  "name": "Galang",
  "email": "galang@example.com",
  "message": "Halo, saya ingin demo."
}
Respons sukses:
{
  "success": true
}
Respons umum:
StatusKapan terjadi
400Field wajib tidak lengkap atau email tidak valid
429Rate limit kontak tercapai
503Fitur contact belum aktif atau env belum siap
500Resend gagal mengirim email
PropertiNilai
AuthTidak perlu login
Feature gateWaitlist feature harus aktif
Rate limit5 request per jam per IP
TujuanMenyimpan lead ke tabel waitlist
Request body:
{
  "email": "galang@example.com",
  "name": "Galang"
}
Respons sukses:
{
  "success": true
}
Respons umum:
StatusKapan terjadi
400Email tidak valid
409Email sudah pernah terdaftar
429Rate limit waitlist tercapai
503Fitur waitlist belum aktif atau env belum siap
500Insert ke database gagal
PropertiNilai
AuthTidak perlu login
TujuanMengecek readiness fitur dan database
Respons inti:
{
  "status": "ok",
  "payment_provider": "doku",
  "checks": {
    "supabase_public": true,
    "supabase_service_role": true,
    "resend": true
  },
  "database": {
    "ok": true,
    "latency_ms": 24
  }
}
Catatan:
  • status 200 dipakai saat sistem sehat untuk fitur aktif,
  • status 503 dipakai saat ada fitur aktif yang belum siap atau check database gagal,
  • respons juga membawa map per fitur yang berisi enabled, missing_env, dan disabled_by_flag.

Endpoint untuk user login

PropertiNilai
AuthWajib login
Feature gatePayments harus aktif dan siap
Rate limit5 request per 15 menit per user
TujuanMembuat pending payment dan sesi checkout provider
Request body:
{
  "plan": "PRO"
}
Respons sukses Midtrans:
{
  "provider": "midtrans",
  "token": "snap-token",
  "orderId": "KK-1742360000000-AB12CD34"
}
Respons sukses Doku:
{
  "provider": "doku",
  "payment_url": "https://sandbox.doku.com/...",
  "orderId": "KK-1742360000000-AB12CD34"
}
Respons umum:
StatusKapan terjadi
400plan tidak valid atau tidak tersedia
401User belum login
429Rate limit payment tercapai
503Payments feature belum siap atau provider belum terkonfigurasi
500Gagal membuat record payment
PropertiNilai
AuthWajib login
TujuanCancel atau resume subscription aktif
Request body:
{
  "action": "cancel"
}
Nilai valid:
  • cancel
  • resume
Respons sukses:
{
  "success": true,
  "status": "cancel_at_period_end"
}
Atau:
{
  "success": true,
  "status": "active"
}
Respons umum:
StatusKapan terjadi
400Action tidak valid
401User belum login
503Konfigurasi server untuk billing belum siap
PropertiNilai
AuthWajib login
TujuanMenyimpan nama lengkap dan referensi avatar profile
Request body:
{
  "full_name": "Galang Pratama",
  "avatar_path": "user-id/avatar",
  "avatar_url": "https://signed-url.example.com/avatar"
}
Respons sukses:
{
  "success": true,
  "profile": {
    "full_name": "Galang Pratama",
    "avatar_path": "user-id/avatar",
    "avatar_url": "https://signed-url.example.com/avatar"
  }
}
Respons umum:
StatusKapan terjadi
400Body profile tidak valid
401User belum login
500Update profile gagal
503Konfigurasi write server-side belum siap
PropertiNilai
AuthWajib login
Feature gateAuth harus aktif
TujuanMembuat signed upload URL untuk avatar
Request body:
{
  "fileSize": 180000,
  "fileType": "image/png"
}
Respons sukses:
{
  "bucket": "avatars",
  "path": "user-id/avatar",
  "token": "signed-upload-token"
}
Respons umum:
StatusKapan terjadi
400Ukuran file lebih dari 2 MB atau MIME type tidak didukung
401User belum login
500Gagal membuat signed upload URL
503Auth feature belum aktif

Endpoint admin

PropertiNilai
AuthWajib login
AuthorizationWajib role admin
TujuanMengubah role user menjadi admin atau member
Request body:
{
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "role": "admin"
}
Respons sukses:
{
  "success": true,
  "user_id": "550e8400-e29b-41d4-a716-446655440000",
  "role": "admin"
}
Respons umum:
StatusKapan terjadi
400Body invalid atau admin mencoba menurunkan role dirinya sendiri
401User belum login
403User login tetapi bukan admin
500Update role gagal
503Fitur admin belum siap dari sisi server

Endpoint AI

PropertiNilai
AuthWajib login
Rate limitBerdasarkan plan user, per 5 menit
TujuanStreaming chat AI
Request body:
{
  "provider": "openai",
  "messages": [
    {
      "role": "user",
      "content": "Bantu saya merangkum brief ini."
    }
  ]
}
Respons sukses:
  • stream UI message response, bukan JSON biasa,
  • usage dicatat setelah stream selesai.
Respons umum:
StatusKapan terjadi
400messages tidak dikirim
401User belum login
429Rate limit request atau monthly usage limit tercapai
503Provider AI belum dikonfigurasi
PropertiNilai
AuthWajib login
Rate limitBerdasarkan plan user, per 5 menit
TujuanOne-shot text generation
Request body:
{
  "provider": "openai",
  "prompt": "Buat deskripsi singkat produk",
  "system": "Gunakan gaya bahasa formal"
}
Respons sukses:
{
  "text": "Deskripsi hasil generate...",
  "usage": {
    "inputTokens": 20,
    "outputTokens": 120
  }
}
Respons umum:
StatusKapan terjadi
400prompt tidak dikirim
401User belum login
429Rate limit request atau monthly usage limit tercapai
503Provider AI belum dikonfigurasi

Endpoint webhook provider

Gunakan endpoint ini sebagai callback dari Midtrans, bukan dari browser user.Yang diverifikasi:
  • order_id
  • status_code
  • gross_amount
  • signature_key
  • transaction_status
Perilaku penting:
  • signature invalid menghasilkan 401,
  • payload invalid menghasilkan 400,
  • payment record tidak ditemukan menghasilkan 404,
  • duplicate event bisa mengembalikan { "received": true, "duplicate": true },
  • event valid akan memperbarui payments, bisa mengaktifkan subscriptions, lalu menulis webhook_events dan audit_logs.
Gunakan endpoint ini sebagai callback dari Doku JOKUL, bukan dari browser user.Yang diverifikasi:
  • order.invoice_number
  • order.amount
  • transaction.status
  • transaction.original_request_id
  • security.check_word
Perilaku penting:
  • signature invalid menghasilkan 401,
  • payload invalid menghasilkan 400,
  • payment record tidak ditemukan menghasilkan 404,
  • duplicate event bisa diidentifikasi lewat webhook_events,
  • event valid memperbarui payments, bisa mengaktifkan subscriptions, lalu menulis audit trail.
Route /auth/confirm adalah callback auth, bukan endpoint /api. Untuk memahami perannya dalam login, OTP, dan OAuth flow, baca Flow end-to-end.