Pengantar API
Ada dua cara berbicara dengan Celestian secara terprogram:
| Untuk | Protokol | Bagian |
|---|---|---|
| Aplikasi, skrip, dan integrasi yang mengelola atau membaca data | HTTP + JSON dengan Personal Access Token (PAT) | Halaman ini dan Contoh alur lengkap |
| Perangkat yang mengirim data | MQTT dengan ID dan key device | Menyambungkan perangkat |
Alur umum data: device publish ke channel lewat MQTT → rule (Channel Subscriber → Internal DB) menyimpan → dibaca lewat API, halaman Messages, atau dashboard. Tanpa rule penyimpanan, pesan diterima tetapi tidak disimpan.
Konsep
Section titled “Konsep”- Workspace adalah batas data. Semua endpoint ada di bawah
/api/v1/workspaces/{ws}/..., dengan{ws}berupa route (misalnyagudang-nusantara) atau UUID. - PAT adalah token milik satu user, terkunci ke satu workspace. Hak efektif = hak user itu ∩ scope token. Token tidak bisa memberi lebih dari yang dimiliki pemiliknya.
- Dengan PAT hanya rute
/api/v1/workspaces/...yang bisa dipakai. Mengelola token, profil, dan aksi manajemen akses (role, member, policy) tidak tersedia. Rute lain menjawab403 pat.not_allowed.
Membuat token
Section titled “Membuat token”Cara termudah: di aplikasi, Profil → Personal Access Tokens → Buat. Pilih workspace, masa berlaku (1 sampai 365 hari), dan hak (scope). Nilai token hanya tampil sekali. Bila hilang, buat ulang atau gunakan Regenerate.
Lewat API (butuh sesi login, bukan PAT):
curl -X POST https://celestian.contoh.id/api/v1/users/me/tokens \ -H "Authorization: Bearer <access-token-sesi>" -H "Content-Type: application/json" \ -d '{ "name": "integrasi-contoh", "description": "baca dan tulis data gudang", "workspaceId": "<uuid-workspace>", "durationDays": 30, "blocks": [ {"scope": "workspace", "actions": ["read"], "effect": "allow"}, {"scope": "channel", "actions": ["read","write","connect","publish","subscribe"], "effect": "allow"}, {"scope": "device", "actions": ["read","write","connect"], "effect": "allow"}, {"scope": "rule", "actions": ["read","write","execute"], "effect": "allow"} ] }'Respons 201:
{ "secret": "tpat_nuZbn7p9P…", "token": { "id": "…", "name": "integrasi-contoh", "workspaceRoute": "gudang-nusantara", "prefix": "tpat_nuZb", "durationDays": 30, "expiresAt": "2026-11-01T22:41:37+07:00", "lastUsedAt": null, "status": "active", "blocks": [ … ] }}secret (diawali tpat_) adalah yang dipakai di header.
Hanya effect: "allow". Aksi manajemen akses ditolak untuk PAT: manage, member.invite, role.manage, policy.manage, serta *. Setiap blok memuat scope, actions, dan opsional pembatas objectId atau tags. Katalog aksi lengkap ada di Katalog izin dan di GET /api/v1/permissions/catalog.
Prinsip: beri token hanya aksi yang dibutuhkan. Integrasi pembaca cukup channel.read.
Autentikasi
Section titled “Autentikasi”Authorization: Bearer tpat_<token>Alamat dasar mengikuti alamat publik aplikasi:
https://<domain>/api/v1/workspaces/{ws}/...Hanya Bearer tpat_… yang diterima, dan badan permintaan dibatasi 2 MiB. Token yang dicabut atau kedaluwarsa menjawab 401.
export CELESTIAN=https://celestian.contoh.idexport TOKEN=tpat_…export WS=gudang-nusantaracurl -s "$CELESTIAN/api/v1/workspaces/$WS" -H "Authorization: Bearer $TOKEN"Respons dan galat
Section titled “Respons dan galat”Sukses: JSON sesuai endpoint, atau 204 tanpa badan. Galat selalu satu bentuk:
{ "code": "validation_failed", "message": "input tidak valid", "fieldErrors": { "route": "channel.route_invalid" } }code stabil dan aman diproses program; message hanya untuk manusia; fieldErrors (opsional) memetakan nama field ke kode galat. Daftar kode: Kode galat.
Daftar, filter, dan paginasi
Section titled “Daftar, filter, dan paginasi”Endpoint daftar mengembalikan objek di dalam kunci jamak beserta penomoran:
{ "channels": [ { "id": "…", "name": "Telemetri Gudang", "route": "telemetri-gudang", "tags": ["telemetri"], "status": "enabled" } ], "total": 1, "page": 1, "limit": 10 }Query umum: ?search=&field=name|route|tag|id&status=enabled|disabled|all&sort=&page=1&limit=20 (limit: 10, 20, 50, 100). Untuk field=tag: a,b = salah satu (OR), a+b = semuanya (AND).
Pesan memakai kursor waktu, bukan nomor halaman: kirim ulang cursor dari page.nextCursor untuk halaman berikutnya. Waktu memakai RFC 3339 (2026-10-02T00:00:00Z).