Endpoint summary
| Group | Main endpoints |
|---|---|
| Public | POST /api/contact, POST /api/waitlist, GET /api/health |
| Logged-in user | POST /api/payments, POST /api/subscription, POST /api/profile, POST /api/profile/avatar |
| Admin | POST /api/admin/users/role |
| AI | POST /api/ai/chat, POST /api/ai/generate |
| Provider callback | POST /api/webhooks/midtrans, POST /api/webhooks/doku |
Public endpoints
POST /api/contact
POST /api/contact
| Property | Value |
|---|---|
| Auth | No login required |
| Feature gate | Contact feature must be active |
| Rate limit | 5 requests per hour per IP |
| Purpose | Send a contact-form message through Resend |
| Status | When it happens |
|---|---|
400 | Required fields are missing or the email is invalid |
429 | Contact rate limit is exceeded |
503 | The contact feature is not active or env is incomplete |
500 | Resend fails to send the email |
POST /api/waitlist
POST /api/waitlist
| Property | Value |
|---|---|
| Auth | No login required |
| Feature gate | Waitlist feature must be active |
| Rate limit | 5 requests per hour per IP |
| Purpose | Save a lead into the waitlist table |
| Status | When it happens |
|---|---|
400 | The email is invalid |
409 | The email is already registered |
429 | The waitlist rate limit is exceeded |
503 | The waitlist feature is not active or env is incomplete |
500 | Database insert fails |
GET /api/health
GET /api/health
| Property | Value |
|---|---|
| Auth | No login required |
| Purpose | Check feature readiness and database availability |
- it returns
200when active features are healthy, - it returns
503when an active feature is still missing required config or the database check fails, - the response also includes a per-feature map with
enabled,missing_env, anddisabled_by_flag.
Logged-in user endpoints
POST /api/payments
POST /api/payments
| Property | Value |
|---|---|
| Auth | Login required |
| Feature gate | Payments must be active and ready |
| Rate limit | 5 requests per 15 minutes per user |
| Purpose | Create a pending payment and start the provider checkout session |
| Status | When it happens |
|---|---|
400 | plan is invalid or unavailable |
401 | The user is not logged in |
429 | Payment rate limit is exceeded |
503 | The payments feature is not ready or the provider is not configured |
500 | The payment record cannot be created |
POST /api/subscription
POST /api/subscription
| Property | Value |
|---|---|
| Auth | Login required |
| Purpose | Cancel or resume the active subscription |
cancelresume
| Status | When it happens |
|---|---|
400 | The action value is invalid |
401 | The user is not logged in |
503 | Server-side billing configuration is not ready |
POST /api/profile
POST /api/profile
| Property | Value |
|---|---|
| Auth | Login required |
| Purpose | Save full name and avatar references for the current user |
| Status | When it happens |
|---|---|
400 | The profile body is invalid |
401 | The user is not logged in |
500 | The profile update fails |
503 | Server-side write configuration is not ready |
POST /api/profile/avatar
POST /api/profile/avatar
| Property | Value |
|---|---|
| Auth | Login required |
| Feature gate | Auth must be active |
| Purpose | Create a signed upload URL for avatars |
| Status | When it happens |
|---|---|
400 | The file is larger than 2 MB or the MIME type is unsupported |
401 | The user is not logged in |
500 | The signed upload URL cannot be created |
503 | The auth feature is not available |
Admin endpoint
POST /api/admin/users/role
POST /api/admin/users/role
| Property | Value |
|---|---|
| Auth | Login required |
| Authorization | admin role required |
| Purpose | Change a user’s role to admin or member |
| Status | When it happens |
|---|---|
400 | The body is invalid or an admin tries to demote their own account |
401 | The user is not logged in |
403 | The user is logged in but is not an admin |
500 | The role update fails |
503 | The admin feature is not ready server-side |
AI endpoints
POST /api/ai/chat
POST /api/ai/chat
| Property | Value |
|---|---|
| Auth | Login required |
| Rate limit | Based on the user’s plan, per 5 minutes |
| Purpose | Stream AI chat responses |
- returns a UI message stream rather than a plain JSON object,
- usage is tracked after the stream finishes.
| Status | When it happens |
|---|---|
400 | messages is missing |
401 | The user is not logged in |
429 | Request rate limit or monthly usage limit is exceeded |
503 | The AI provider is not configured |
POST /api/ai/generate
POST /api/ai/generate
| Property | Value |
|---|---|
| Auth | Login required |
| Rate limit | Based on the user’s plan, per 5 minutes |
| Purpose | Generate one-off text output |
| Status | When it happens |
|---|---|
400 | prompt is missing |
401 | The user is not logged in |
429 | Request rate limit or monthly usage limit is exceeded |
503 | The AI provider is not configured |
Provider webhook endpoints
POST /api/webhooks/midtrans
POST /api/webhooks/midtrans
Use this endpoint as a Midtrans callback, not as a browser-facing route.Verified fields:
order_idstatus_codegross_amountsignature_keytransaction_status
- invalid signature returns
401, - invalid payload returns
400, - missing payment record returns
404, - duplicate delivery can return
{ "received": true, "duplicate": true }, - valid events update
payments, may activatesubscriptions, and write intowebhook_eventsandaudit_logs.
POST /api/webhooks/doku
POST /api/webhooks/doku
Use this endpoint as a Doku JOKUL callback, not as a browser-facing route.Verified fields:
order.invoice_numberorder.amounttransaction.statustransaction.original_request_idsecurity.check_word
- invalid signature returns
401, - invalid payload returns
400, - missing payment record returns
404, - duplicate delivery is traceable through
webhook_events, - valid events update
payments, may activatesubscriptions, and write an audit trail.
/auth/confirm is an auth callback route, not an /api endpoint. To understand where it fits in login, OTP, and OAuth flows, read End-to-end flows.