Your first call in four steps.
A plain REST API, JSON in and out. The first two calls cost nothing, so you can prove your key before a credit moves.
-
01
Get a key
Make a key and keep it on your server. It is shown once.
export STAGLIGHT_API_KEY="sl_live_..." -
02
Check it for free
These two calls cost nothing: one says who you are and your balance, the other prices a job.
curl -s https://mobyvid.com/api/v1/me \ -H "Authorization: Bearer $STAGLIGHT_API_KEY"curl -s -X POST https://mobyvid.com/api/v1/estimate \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"op": "image.nano-banana-pro", "params": {"prompt": "A premium product shot of a glass serum bottle on wet stone, soft window light", "aspect_ratio": "4:5"}}' -
03
Run a job
One POST starts Nano Banana Pro. It is charged once, then this code waits for the result and gets the file.
Open Nano Banana Pro# 1. Create the job. It is charged once and refunded if it fails. JOB_ID=$(curl -s -X POST https://mobyvid.com/api/v1/jobs \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "op": "image.nano-banana-pro", "params": { "prompt": "A premium product shot of a glass serum bottle on wet stone, soft window light", "aspect_ratio": "4:5" }, "max_credits": 16 }' | jq -r .id) # 2. Poll until it finishes. Each call waits up to 30 seconds. while :; do JOB=$(curl -s "https://mobyvid.com/api/v1/jobs/$JOB_ID?wait=30" -H "Authorization: Bearer $STAGLIGHT_API_KEY") case "$(echo "$JOB" | jq -r .status)" in queued|running) ;; *) break ;; esac done # 3. Download the result from outputs[0].download_url. DOWNLOAD_URL=$(echo "$JOB" | jq -r '.outputs[0].download_url') curl -L -o result.png "$DOWNLOAD_URL"import os, uuid, requests BASE = "https://mobyvid.com/api/v1" HEADERS = {"Authorization": f"Bearer {os.environ['STAGLIGHT_API_KEY']}"} # 1. Create the job. It is charged once and refunded if it fails. r = requests.post(f"{BASE}/jobs", timeout=60, headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())}, json={ "op": "image.nano-banana-pro", "params": { "prompt": "A premium product shot of a glass serum bottle on wet stone, soft window light", "aspect_ratio": "4:5" }, "max_credits": 16 }) r.raise_for_status() job = r.json() # 2. Poll until it finishes. Each call waits up to 30 seconds. while job["status"] in ("queued", "running"): job = requests.get(f"{BASE}/jobs/{job['id']}", headers=HEADERS, params={"wait": 30}, timeout=60).json() # 3. Download the result from outputs[0].download_url. print(job["outputs"][0]["download_url"] if job["outputs"] else job["data"] or job["error"])// Node 18 or newer. Save as run.mjs: top-level await needs a module. const BASE = "https://mobyvid.com/api/v1"; const headers = { Authorization: `Bearer ${process.env.STAGLIGHT_API_KEY}` }; // 1. Create the job. It is charged once and refunded if it fails. let res = await fetch(`${BASE}/jobs`, { method: "POST", headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ "op": "image.nano-banana-pro", "params": { "prompt": "A premium product shot of a glass serum bottle on wet stone, soft window light", "aspect_ratio": "4:5" }, "max_credits": 16 }), }); if (!res.ok) throw new Error((await res.json()).error.message); let job = await res.json(); // 2. Poll until it finishes. Each call waits up to 30 seconds. while (job.status === "queued" || job.status === "running") { job = await (await fetch(`${BASE}/jobs/${job.id}?wait=30`, { headers })).json(); } // 3. Download the result from outputs[0].download_url. console.log(job.outputs[0]?.download_url ?? job.data ?? job.error);POST /api/v1/jobsjob.idGET /api/v1/jobs/{id}?wait=30download_url -
04
Watch it
Every job, charge and refund shows in your workspace. A job is always in one of these states.
Open Task logsJob status
queued- Accepted and charged. Waiting for its turn.
running- The model is working on it.
succeeded- Done. The files are in outputs.
failed- It did not work. The credits came back on their own.
canceled- Canceled before it started. The credits came back.
One prompt. Your agent takes it from here.
Give Claude Code, Codex or Cursor the context to build your Staglight integration. Start with the docs, not a blank page.
Open the documentation indexRead the Staglight API documentation:
https://mobyvid.com/llms.txt
https://mobyvid.com/en/docs/api
Build a server-side integration that creates a product image
with POST /api/v1/jobs (op "image.nano-banana-pro"), then polls
GET /api/v1/jobs/{id}?wait=30 until the job has finished.
Read the key from the STAGLIGHT_API_KEY environment variable, never in browser code.
Check the balance first (GET /api/v1/me) and the price (POST /api/v1/estimate).
Send an Idempotency-Key with every paid request. After a timeout, do not retry
blindly: look the job up with GET /api/v1/jobs?idempotency_key=... first.
Return the finished image when its status is succeeded.