API ARstudio
Buat dan update pengalaman AR dari aplikasimu: CMS, toko online, aplikasi sekolah. Hasilnya link + QR yang langsung jalan di HP.
Base URL: {{BASE}}/api/v1 · Format JSON · Tersedia di paket Pro & Bisnis.
Autentikasi
Buat API key di Dashboard → API key, lalu kirim di setiap request:
Authorization: Bearer arb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Simpan key di server kamu, jangan di kode frontend. Key bisa dicabut kapan saja dari dashboard.
Batas & error
| Paket | Request / menit | AR online | Penyimpanan |
|---|---|---|---|
| Pro | 60 | 25 | 2 GB |
| Bisnis | 600 | 500 | 20 GB |
Header X-RateLimit-Remaining menunjukkan sisa kuota. Error selalu berbentuk {"error": "pesan"}.
| Kode | Arti |
|---|---|
| 400 | Input tidak valid (mis. aset yang dirujuk scene belum di-upload — lihat missing) |
| 401 | API key salah / dicabut |
| 402 | Butuh paket lebih tinggi atau kuota habis (upgrade: true) |
| 403 / 404 | Project bukan milikmu / tidak ada |
| 413 | File lebih dari 200 MB |
| 429 | Rate limit — tunggu sesuai header Retry-After |
Alur publish
- Buat project → dapat
iddanurl. - Upload aset (gambar target, file .mind, model, video…) dengan ID buatanmu sendiri (4–32 huruf kecil/angka).
- Kirim scene yang merujuk ID aset tadi → project langsung live di
url.
# 1. buat project curl -X POST {{BASE}}/api/v1/projects \ -H "Authorization: Bearer $ARB_KEY" -H "Content-Type: application/json" \ -d '{"name":"Katalog Sepatu"}' # → {"id":"a1b2c3d4e5","url":"{{BASE}}/p/a1b2c3d4e5", ...} # 2. upload aset (body = file mentah) curl -X PUT {{BASE}}/api/v1/projects/a1b2c3d4e5/assets/poster01 \ -H "Authorization: Bearer $ARB_KEY" -H "Content-Type: image/jpeg" --data-binary @poster.jpg curl -X PUT {{BASE}}/api/v1/projects/a1b2c3d4e5/assets/target01 \ -H "Authorization: Bearer $ARB_KEY" -H "Content-Type: application/octet-stream" --data-binary @targets.mind curl -X PUT {{BASE}}/api/v1/projects/a1b2c3d4e5/assets/sepatu01 \ -H "Authorization: Bearer $ARB_KEY" -H "Content-Type: model/gltf-binary" --data-binary @sepatu.glb # 3. simpan scene → live curl -X PUT {{BASE}}/api/v1/projects/a1b2c3d4e5/scene \ -H "Authorization: Bearer $ARB_KEY" -H "Content-Type: application/json" -d @scene.json
Upload ulang ke ID yang sama = ganti file. Kirim ulang scene kapan saja untuk update — link & QR tetap sama.
Endpoint
| GET | /me | Akun, paket, pemakaian |
| GET | /projects | Daftar project (+ jumlah dibuka & scan) |
| POST | /projects | Buat project {"name"} |
| GET | /projects/{id} | Detail + scene + daftar aset |
| PUT | /projects/{id}/assets/{assetId} | Upload / ganti aset |
| PUT | /projects/{id}/scene | Simpan scene → live |
| GET | /projects/{id}/stats | Statistik: dibuka, scan per target, tap per objek, per hari |
| DELETE | /projects/{id} | Hapus (link mati) |
| ARpoi — portal POI kota/wisata | ||
| GET | /portals | Daftar portal ARpoi milikmu |
| GET | /portals/{id}/pois | Semua POI portal |
| POST | /portals/{id}/pois | Tambah satu POI {name, lat, lng, category, …} |
| POST | /portals/{id}/pois/import | Impor massal {"mode":"append"|"replace","items":[…]} — kategori baru dibuat otomatis |
| PUT | /portals/{id}/pois/{poiId} | Ubah sebagian field POI |
| DELETE | /portals/{id}/pois/{poiId} | Hapus POI |
Field POI: name, lat, lng, category, description, address, phone, whatsapp, website, hours, price, tags, images (URL), featured, ar. Cocok untuk sinkron otomatis dari database dinas pariwisata (mis. cron harian dengan mode: "replace").
Spesifikasi lengkap (bisa diimpor ke Postman / Insomnia / generator SDK): /api/v1/openapi.json
Format scene
Lebar gambar target = 1 unit. Marker rebah di bidang XZ, +Y keluar dari gambar, sisi atas gambar ke arah −Z. Rotasi dalam derajat.
{
"name": "Katalog Sepatu",
"targets": [{ "id": "t1", "name": "Poster", "image": "poster01", "aspect": 1.414 }],
"mind": { "asset": "target01", "key": "poster01" },
"entities": [
{ "id": "e1", "name": "Sepatu", "type": "model", "targetId": "t1",
"position": [0, 0, 0], "rotation": [0, 0, 0], "scale": [0.5, 0.5, 0.5], "visible": true,
"props": { "asset": "sepatu01" }, "anim": { "type": "spin", "speed": 0.5 },
"onTap": [{ "type": "openWeb", "url": "https://toko.id/sepatu" }], "onFound": [] },
{ "id": "e2", "name": "Video", "type": "youtube", "targetId": "t1",
"position": [0, 0.3, -0.3], "rotation": [0, 0, 0], "scale": [0.8, 0.8, 0.8], "visible": false,
"props": { "url": "https://youtu.be/aqz-KE-bpKQ", "aspect": 0.5625, "autoplay": true },
"anim": { "type": "none", "speed": 1 }, "onTap": [], "onFound": [] }
]
}
| type | props penting |
|---|---|
| model, image, video, audio | asset; video: loop, muted, autoplay, chroma, chromaColor |
| youtube, web | url, aspect (tinggi/lebar) |
| text | text, textColor, bgColor, fontSize |
| box, sphere, cylinder, cone, torus, plane | color, opacity, metalness, roughness |
Aksi onTap / onFound: openUrl, openWeb (pakai url), atau toggle, show, hide, play, pause (pakai target = id entity). Animasi: none, spin, bob, pulse, clip.
Image target (.mind)
Tracking butuh file .mind hasil compile semua gambar target (urutan = urutan targets). Cara mendapatkannya:
- Buat & publish sekali di editor → Export
.arb(zip berisiproject.json+ semua aset termasuk .mind) → pakai ulang lewat API. - Atau compile dengan MindAR Image Compiler (format v2).
Satu file .mind bisa dipakai berulang untuk banyak project selama gambarnya sama — cukup ganti konten scene.
Embed & QR
Setiap project punya url (jadikan QR) dan embed untuk ditanam di website:
<iframe src="{{BASE}}/p/a1b2c3d4e5"
allow="camera; gyroscope; accelerometer; xr-spatial-tracking; autoplay; fullscreen"
style="width:100%;aspect-ratio:9/16;border:0;border-radius:16px"></iframe>
Atribut allow="camera" wajib supaya kamera bisa dipakai di dalam iframe. Website harus HTTPS.
Contoh JavaScript (Node 18+)
const BASE = '{{BASE}}/api/v1';
const H = { Authorization: `Bearer ${process.env.ARB_KEY}` };
const call = async (method, path, body, type = 'application/json') => {
const r = await fetch(BASE + path, { method, body,
headers: { ...H, ...(body ? { 'Content-Type': type } : {}) } });
if (!r.ok) throw new Error((await r.json()).error);
return r.status === 204 ? null : r.json();
};
const p = await call('POST', '/projects', JSON.stringify({ name: 'Brosur' }));
await call('PUT', `/projects/${p.id}/assets/poster01`, await fs.readFile('poster.jpg'), 'image/jpeg');
await call('PUT', `/projects/${p.id}/assets/target01`, await fs.readFile('targets.mind'), 'application/octet-stream');
const live = await call('PUT', `/projects/${p.id}/scene`, JSON.stringify(scene));
console.log('AR siap:', live.url);