XPlor3
REST API

Alur generate

Lima langkah dari memilih model sampai mengunduh berkas hasil, dengan contoh curl, JavaScript, dan Python.

Alurnya selalu sama untuk gambar, video, dan suara: baca field model, (kalau perlu) unggah berkas acuan, mulai job, tunggu sampai selesai, lalu minta tautan unduhan.

Baca field model

GET /v1/models mengembalikan seluruh katalog. Endpoint ini publik, tidak butuh kunci. Setiap model membawa slug (dikirim sebagai modelSlug), inputSchema.fields (field yang diterimanya), dan defaults (nilai bawaannya).

curl https://api.xplor3.space/v1/models

Potongan untuk Nano Banana 2:

{
  "slug": "nano-banana-2",
  "kind": "IMAGE",
  "displayName": "Nano Banana 2",
  "creditCost": 4.8,
  "inputSchema": {
    "fields": [
      { "name": "prompt", "type": "textarea", "required": true, "maxLength": 20000 },
      { "name": "tier", "type": "select", "options": ["standard", "lite"], "default": "standard" },
      { "name": "reference_images", "type": "image", "max": 14 },
      { "name": "aspect_ratio", "type": "select", "options": ["auto", "1:1", "16:9", "9:16"], "default": "auto" },
      { "name": "resolution", "type": "select", "options": ["1K", "2K", "4K"], "default": "1K" }
    ]
  },
  "defaults": { "tier": "standard", "resolution": "1K", "aspect_ratio": "auto" }
}

creditCost adalah biaya termurah model itu. Biaya pasti sebuah request bergantung pada pengaturan yang kamu kirim, dan dikembalikan saat job dibuat.

Semua field setiap model, nilai yang diterimanya, dan aturan per tier atau mode juga ada dalam bentuk tabel di Referensi model.

Unggah berkas acuan (opsional)

Untuk model yang menerima gambar, video, atau audio acuan, unggah berkasnya dulu. Jawabannya memuat id unggahan, yang lalu dikirim di field media model.

curl https://api.xplor3.space/v1/uploads \
  -H "Authorization: Bearer $XPLOR3_API_KEY" \
  -F "[email protected]"

Kalau tidak bisa mengirim multipart, POST /v1/uploads/base64 menerima JSON { "fileName": "produk.jpg", "dataBase64": "..." }.

Mulai job

POST /v1/jobs dengan modelSlug dan input. Field yang tidak dikirim memakai nilai dari defaults. Kredit dipotong saat ini juga.

curl https://api.xplor3.space/v1/jobs \
  -H "Authorization: Bearer $XPLOR3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "modelSlug": "nano-banana-2",
    "input": {
      "prompt": "Secangkir kopi di meja kayu dekat jendela, cahaya pagi, foto produk close-up",
      "aspect_ratio": "4:5",
      "resolution": "1K"
    },
    "variations": 2
  }'

Jawabannya 201 Created:

{ "jobId": "cm...", "status": "QUEUED", "creditCost": 19.2, "balance": 101.2 }

creditCost sudah termasuk semua variasi, dan balance adalah sisa saldo setelah dipotong.

Tunggu sampai selesai

Cara paling hemat: kirim webhookUrl di body POST /v1/jobs, dan XPlor3 akan mengirim POST ke alamat itu saat job berakhir. Caranya ada di Webhook. Kalau kodemu tidak bisa menerima request dari internet, baca GET /v1/jobs/{id} setiap beberapa detik sampai status berhenti di salah satu status akhir.

StatusArtinya
QUEUEDMenunggu giliran. Masih bisa dibatalkan dengan kredit kembali
SUBMITTEDSudah dikirim ke model
RUNNINGSedang dikerjakan; progress bergerak dari 0 ke 100
SUCCEEDEDSelesai; id berkas hasilnya ada di assetIds
FAILEDGagal; kreditnya sudah dikembalikan, alasannya di failCode dan failMessage
CANCELEDDibatalkan saat masih antre; kreditnya sudah dikembalikan

Gambar biasanya selesai dalam hitungan detik sampai satu menit; video bisa beberapa menit. Jeda 3 sampai 5 detik antar-pembacaan sudah cukup dan jauh di bawah batas request.

Sebagai ganti polling, GET /v1/jobs/{id}/events mengirim perubahan status sebagai Server-Sent Events dan menutup koneksinya sendiri saat job selesai.

Ambil tautan unduhan

Kirim assetIds ke POST /v1/assets/urls. Setiap tautan bertanda tangan dan berlaku 15 menit; minta lagi kapan saja kalau sudah kedaluwarsa. Tambahkan "download": true supaya berkas terunduh dengan nama yang rapi.

curl https://api.xplor3.space/v1/assets/urls \
  -H "Authorization: Bearer $XPLOR3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["cm...", "cm..."], "download": true }'
{
  "items": [
    { "id": "cm...", "url": "https://...", "expiresAt": "2026-10-23T08:30:00.000Z" }
  ]
}

Contoh lengkap

generate.mjs
const API = "https://api.xplor3.space/v1";
const headers = {
  Authorization: `Bearer ${process.env.XPLOR3_API_KEY}`,
  "Content-Type": "application/json",
};

async function call(path, init = {}) {
  const response = await fetch(`${API}${path}`, { ...init, headers });
  const body = await response.json();
  if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
  return body;
}

const job = await call("/jobs", {
  method: "POST",
  body: JSON.stringify({
    modelSlug: "nano-banana-2",
    input: { prompt: "Sepatu lari putih di lintasan atletik saat matahari terbenam" },
  }),
});
console.log(`Job ${job.jobId}, ${job.creditCost} kredit, sisa ${job.balance}`);

const FINISHED = ["SUCCEEDED", "FAILED", "CANCELED"];
let detail = await call(`/jobs/${job.jobId}`);
while (!FINISHED.includes(detail.status)) {
  await new Promise((resolve) => setTimeout(resolve, 4000));
  detail = await call(`/jobs/${job.jobId}`);
}

if (detail.status !== "SUCCEEDED") {
  throw new Error(`Job berakhir ${detail.status}: ${detail.failMessage ?? ""}`);
}

const { items } = await call("/assets/urls", {
  method: "POST",
  body: JSON.stringify({ ids: detail.assetIds, download: true }),
});
for (const item of items) console.log(item.url);

Tips

  • Mulai dari setelan termurah saat menguji alur, misalnya tier lite atau resolusi 1K, lalu naikkan setelah semuanya berjalan.
  • Simpan jobId di sistemmu. Job yang dimulai lewat API juga muncul di Riwayat studio, jadi hasilnya bisa diperiksa dari sana.
  • Masukkan ke proyek dengan menambahkan collectionId di body POST /v1/jobs. Id proyek ada di GET /v1/collections.
  • Lewati loop polling di produksi dengan menambahkan webhookUrl; loop di atas untuk skrip yang tidak bisa menerima request. Lihat Webhook.

Di halaman ini