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

PaketRequest / menitAR onlinePenyimpanan
Pro60252 GB
Bisnis60050020 GB

Header X-RateLimit-Remaining menunjukkan sisa kuota. Error selalu berbentuk {"error": "pesan"}.

KodeArti
400Input tidak valid (mis. aset yang dirujuk scene belum di-upload — lihat missing)
401API key salah / dicabut
402Butuh paket lebih tinggi atau kuota habis (upgrade: true)
403 / 404Project bukan milikmu / tidak ada
413File lebih dari 200 MB
429Rate limit — tunggu sesuai header Retry-After

Alur publish

  1. Buat project → dapat id dan url.
  2. Upload aset (gambar target, file .mind, model, video…) dengan ID buatanmu sendiri (4–32 huruf kecil/angka).
  3. 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/meAkun, paket, pemakaian
GET/projectsDaftar project (+ jumlah dibuka & scan)
POST/projectsBuat project {"name"}
GET/projects/{id}Detail + scene + daftar aset
PUT/projects/{id}/assets/{assetId}Upload / ganti aset
PUT/projects/{id}/sceneSimpan scene → live
GET/projects/{id}/statsStatistik: dibuka, scan per target, tap per objek, per hari
DELETE/projects/{id}Hapus (link mati)
ARpoi — portal POI kota/wisata
GET/portalsDaftar portal ARpoi milikmu
GET/portals/{id}/poisSemua POI portal
POST/portals/{id}/poisTambah satu POI {name, lat, lng, category, …}
POST/portals/{id}/pois/importImpor 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": [] }
  ]
}
typeprops penting
model, image, video, audioasset; video: loop, muted, autoplay, chroma, chromaColor
youtube, weburl, aspect (tinggi/lebar)
texttext, textColor, bgColor, fontSize
box, sphere, cylinder, cone, torus, planecolor, 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:

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);