Satu API untuk akun, katalog model, chat, kunci akses, dan pemakaian. Halaman ini hanya memuat endpoint yang benar-benar terdaftar di kode yang berjalan, bukan rencana.
https://weind.id
Buat akun, simpan token, lalu panggil endpoint terautentikasi. Semua contoh di bawah bisa disalin apa adanya.
curl -sS -X POST https://weind.id/v1/auth/register \
-H 'Content-Type: application/json' \
-d '{ "email": "[email protected]", "password": "rahasia-yang-panjang", "display_name": "Nama Kamu" }'
# Sudah punya akun? Gunakan POST /v1/auth/login dengan email + password saja.
{ "data": { "user": { "id": "<uuid>", "email": "[email protected]", "displayName": "Nama Kamu" },
"access_token": "<jwt>", "refresh_token": "<token>", "token_type": "Bearer", "expires_in": 900 } }
export TOKEN='<access_token dari langkah 2>'
curl -sS https://weind.id/v1/auth/me -H "Authorization: Bearer $TOKEN"
# { "data": { "user": { ... }, "workspace_id": "<uuid>" } }
curl -sS -X POST https://weind.id/v1/api-keys \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{ "scopes": ["models:read", "chat:write", "usage:read"] }'
# data.key diawali weind_sk_ dan hanya ditampilkan sekali.
Kirim kredensial di header Authorization: Bearer <kredensial>. Server membedakannya dari bentuk nilainya: API key selalu diawali weind_sk_, token sesi tidak.
| Kredensial | Bentuk | Masa berlaku | Dipakai untuk |
|---|---|---|---|
| Token sesi | JWT (access_token) |
expires_in detik, bawaan 15 menit. Diperpanjang lewat refresh token (bawaan 30 hari). |
/v1/auth/me, /v1/auth/workspaces, /v1/usage, /v1/usage/export, /v1/ledger, /v1/reconciliation, dan manajemen /v1/api-keys |
| API key | weind_sk_ + rahasia base64url |
Tanpa kedaluwarsa kecuali Anda mengisi expiresAt; bisa dicabut kapan saja. |
/v1/chat dan endpoint berbayar lain; juga diterima di /v1/api-keys |
access_token adalah JWT bertanda tangan; masa berlakunya dikembalikan sebagai expires_in dalam detik.refresh_token dikirim di body dan diset sebagai cookie httpOnly bernama weind_refresh (path /v1/auth) untuk pemakaian di browser.ws, bukan dari input permintaan. Untuk berganti workspace, panggil ulang /v1/auth/login atau /v1/auth/refresh.chat:read, chat:write, agents:read, agents:write, models:read, usage:read. Minimal satu scope wajib diisi saat membuat.API_KEY_INVALID, API_KEY_REVOKED, API_KEY_EXPIRED.Di development, modul internal menerima header x-weind-workspace dan x-weind-user sebagai jalan pintas identitas. Di produksi keduanya ditolak tanpa syarat: setiap permintaan yang membawanya dijawab 401 dengan kode DEV_AUTH_DISABLED, bahkan bila header Authorization yang sah ikut disertakan.
Jangan pernah mengirim header tersebut ke https://weind.id. Gunakan token sesi atau API key.
curl -sS 'https://weind.id/v1/usage?period=2026-09' -H 'x-weind-workspace: <uuid>'
# 401 { "statusCode": 401, "code": "DEV_AUTH_DISABLED", "error": "Unauthorized",
# "message": "Header autentikasi development tidak diizinkan di produksi." }
Daftar di bawah dibangun dari data di halaman ini dan hanya memuat rute yang terdaftar di kode aplikasi yang berjalan. Buka tiap kelompok untuk melihat detail.
Penangan error yang terpasang di aplikasi /v1 selalu membalas bentuk berikut, sesuai tipe ErrorEnvelope di kode.
{ "error": { "code": "VALIDATION_ERROR",
"message": "Parameter `period` harus \"YYYY-MM\" (mis. 2026-09).",
"request_id": "<id permintaan>", "retryable": false } }
code stabil dan aman untuk dicabang di kode klien; message berbahasa Indonesia dan bisa berubah.request_id juga dikirim sebagai header x-request-id pada setiap respons, termasuk 401, 404, dan 500. Sertakan saat melaporkan masalah.retryable bernilai true untuk kegagalan sementara (rate limit, dependensi tidak sehat). Saat true, hormati header Retry-After.1. Penjaga dev header. Respons DEV_AUTH_DISABLED memakai bentuk ringkas { statusCode, code, error, message } dan dibuat sebelum penangan error berjalan.
2. Endpoint pemakaian. /v1/usage, /v1/usage/export, /v1/ledger, dan /v1/reconciliation punya penangan error sendiri yang mengisi request_id dari header x-request-id yang Anda kirim, sehingga nilainya bisa null.
| Kode | Status | Retryable | Artinya |
|---|---|---|---|
DEV_AUTH_DISABLED | 401 | tidak | Header x-weind-workspace/x-weind-user dikirim ke produksi. |
AUTH_TOKEN_MISSING | 401 | tidak | Kredensial tidak ada, atau token sesi tidak memuat workspace. |
AUTH_TOKEN_INVALID | 401 | tidak | Token sesi tidak valid atau sudah kedaluwarsa. |
AUTH_REFRESH_INVALID | 401 | tidak | Refresh token tidak ada atau tidak berlaku. |
AUTH_INVALID_CREDENTIALS | 401 | tidak | Email atau password salah. Login juga memakai kode ini bila email belum terdaftar. |
AUTH_EMAIL_EXISTS | 409 | tidak | Email sudah terdaftar saat register. |
API_KEY_MISSING | 401 | tidak | Endpoint berbayar dipanggil tanpa API key. |
API_KEY_INVALID | 401 | tidak | API key tidak dikenal. |
API_KEY_REVOKED | 401 | tidak | API key sudah dicabut. |
API_KEY_EXPIRED | 401 | tidak | API key melewati expiresAt. |
VALIDATION_ERROR | 400 | tidak | Body atau query tidak lolos validasi. |
NOT_FOUND | 404 | tidak | Rute atau resource tidak ada. |
IDEMPOTENCY_KEY_REQUIRED | 400 | tidak | Header Idempotency-Key tidak dikirim. |
IDEMPOTENCY_KEY_INVALID | 400 | tidak | Header Idempotency-Key melebihi 255 karakter. |
IDEMPOTENCY_KEY_REPLAYED | 409 | tidak | Key yang sama masih diproses permintaan lain. Ulangi dengan key yang sama setelah jeda singkat. |
IDEMPOTENCY_KEY_MISMATCH | 409 | tidak | Key yang sama dipakai dengan body berbeda. Pakai key baru. |
PAYLOAD_TOO_LARGE | 413 | tidak | Body melebihi batas penjaga keamanan (64 KiB). |
RATE_LIMITED | 429 | ya | Batas laju terlampaui. Lihat Retry-After. |
SERVICE_UNAVAILABLE | 503 | ya | Dependensi sedang tidak sehat. |
INTERNAL_ERROR | 500 | tidak | Kesalahan tak terduga. Sertakan request_id saat melapor. |
Setiap endpoint /v1 dibatasi per workspace; permintaan anonim dihitung terpisah. Aturan khusus yang berlaku untuk permukaan publik ini: chat.send 30/menit (token bucket), api_keys.write 10 per 10 menit, dan api_keys.read ikut aturan global. Endpoint auth, katalog, dan pemakaian memakai aturan global 300 permintaan/menit. Saat terlampaui, jawabannya 429 dengan header Retry-After.
GET /v1/models saat ini mengembalikan array kosong, karena belum ada model yang diaktifkan di database produksi.simulated: true, dan tidak ada permintaan yang benar-benar dikirim ke penyedia model.Spesifikasi mesin-terbaca tersedia di /v1/openapi.yaml, dan Swagger UI bawaan server ada di /v1/docs.