Nano Banana Pro API
Nano Banana Pro — top-tier image generation, backed by Gemini 3 Pro Image. 4K resolution, photorealistic, strong prompt adherence + scene composition. Right choice for hero shots, marketing visuals, product photography.
Quickstart
Image generation uses the /v1/run endpoint with model id + inputs object. The quickstart below shows the synchronous form (blocks for 30–80s). For production we strongly recommend opt-in async mode — see the Async mode section below. Response includes a signed URL to the generated image (fetch within ~24h before the link expires).
bash# 1) Submit the job (async — image generation takes 10-60s, so async + poll is the
# only reliable pattern; a synchronous POST will time out on most platforms).
curl https://api.skillboss.co/v1/run \
-H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-3-pro-image",
"async": true,
"inputs": {
"prompt": "A premium commercial advertising photo of a coffee cup, studio lighting, white background",
"image_urls": [],
"image_size": "2K",
"aspect_ratio": "1:1"
}
}'
# → {"request_id":"<id>","status":"IN_QUEUE","status_url":"https://api.skillboss.co/v1/run/status/<id>", ...}
# 2) Poll status_url every 3-5s until status is "COMPLETED" (or "FAILED").
curl https://api.skillboss.co/v1/run/status/<id> \
-H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY"
# → {"status":"COMPLETED","result":{"generated_images":["https://assets.skillboss.co/...png"], "text_response":"", "finish_reason":"STOP", "usage":{...}}, ...}Your first 200 response is the fastest way to confirm setup. From there, swap in your real prompt and tune the model-specific parameters listed below.
Authentication
Every request must include your wholesale key. The header name depends on the endpoint — match the SDK you're using:
bashAuthorization: Bearer $SKILLBOSS_WHOLESALE_KEYTreat the wholesale key like a password — never commit it to source control or ship it in client-side bundles. Rotate from the wholesale dashboard if exposed. Standard (non-wholesale) console keys are rejected at the gateway with 401.
Code examples
pythonimport os, time, requests
KEY = os.environ["SKILLBOSS_WHOLESALE_KEY"]
HEAD = {"Authorization": f"Bearer {KEY}"}
# 1) Submit the job — async + poll is the only reliable pattern for image gen.
start = requests.post(
"https://api.skillboss.co/v1/run",
headers={**HEAD, "Content-Type": "application/json"},
json={
"model": "google/gemini-3-pro-image",
"async": True,
"inputs": {
"prompt": "A premium commercial advertising photo of a coffee cup, studio lighting, white background",
"image_urls": [],
"image_size": "2K",
"aspect_ratio": "1:1",
},
},
timeout=30,
).json()
status_url = start["status_url"]
# 2) Poll until COMPLETED (or FAILED). Image gen is 10-60s for NB Pro, faster
# for flash models. A 5-minute ceiling is generous; hit FAILED earlier if
# upstream rejects the prompt or a reference URL.
deadline = time.time() + 300
while time.time() < deadline:
poll = requests.get(status_url, headers=HEAD, timeout=30).json()
if poll["status"] == "COMPLETED":
# generated_images[] holds short R2 URLs (assets.skillboss.co/*), not
# signed URLs — they don't expire and can be embedded directly.
print(poll["result"]["generated_images"][0])
break
if poll["status"] == "FAILED":
raise RuntimeError(poll.get("error", "image gen failed"))
time.sleep(3)typescriptconst KEY = process.env.SKILLBOSS_WHOLESALE_KEY
const head = { Authorization: `Bearer ${KEY}` }
// 1) Submit the job — async + poll is the only reliable pattern for image gen.
const start = await fetch("https://api.skillboss.co/v1/run", {
method: "POST",
headers: { ...head, "Content-Type": "application/json" },
body: JSON.stringify({
model: "google/gemini-3-pro-image",
async: true,
inputs: {
prompt: "A premium commercial advertising photo of a coffee cup, studio lighting, white background",
image_urls: [],
image_size: "2K",
aspect_ratio: "1:1",
},
}),
}).then((r) => r.json())
// 2) Poll until COMPLETED (or FAILED). Image gen is 10-60s for NB Pro, faster
// for flash models. A 5-minute ceiling is generous; hit FAILED earlier if
// upstream rejects the prompt or a reference URL.
const deadline = Date.now() + 5 * 60_000
while (Date.now() < deadline) {
const poll = await fetch(start.status_url, { headers: head }).then((r) => r.json())
if (poll.status === "COMPLETED") {
// generated_images[] holds short R2 URLs (assets.skillboss.co/*), not
// signed URLs — they don't expire and can be embedded directly.
console.log(poll.result.generated_images[0])
break
}
if (poll.status === "FAILED") {
throw new Error(poll.error ?? "image gen failed")
}
await new Promise((r) => setTimeout(r, 3000))
}Parameters
Pass the model identifier as a top-level model field, and all generation parameters under an inputs object. The exact set of inputs.* fields depends on the model — see the model card on the wholesale dashboard for advanced options.
Async mode (recommended for production)
Image and video generation can take from tens of seconds to several minutes. The default /v1/run call is synchronous — it holds the HTTP connection until the result is ready, which routinely exceeds client / proxy / serverless function timeouts and pins a worker for the full duration.
Opt into async mode by adding "async": true to the request body (or by supplying webhook_url). Submit returns in <1s with a request_id; you then poll the status URL or receive the result via webhook. This is the standard queue-based pattern used by every async-generation provider — clients designed for that shape work without changes.
bashcurl -X POST https://api.skillboss.co/v1/run \
-H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-3-pro-image",
"inputs": { "prompt": "your prompt here" },
"async": true
}'Response:
json{
"request_id": "c546520207fb4b68b0adce825f9dcf6d",
"status": "IN_QUEUE",
"status_url": "https://api.skillboss.co/v1/run/status/c546520207fb4b68b0adce825f9dcf6d",
"cancel_url": "https://api.skillboss.co/v1/run/cancel/c546520207fb4b68b0adce825f9dcf6d"
}The same request_id is also returned in the x-request-id response header. A separate x-record-id header carries the internal deduct/audit row id — quote it when reporting an issue so support can find the call in our logs. Day-to-day client code only needs request_id.
bashcurl https://api.skillboss.co/v1/run/status/{request_id} \
-H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY"Status enum — the full lifecycle:
Polling loop: hit the status endpoint every 5–10s; stop the moment you see COMPLETED / FAILED / CANCELLED — those are terminal. Result payload (when COMPLETED) is the same shape as the synchronous response — fetched via the result field. We retain completed results for 7 days, then they expire.
bashcurl -X POST https://api.skillboss.co/v1/run/cancel/{request_id} \
-H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY"Returns 200 with cancelled: true on success, 200 idempotent no-op if already terminal, 409if the worker has already started the vendor call (the cost is already being incurred upstream and we don't support mid-flight abort), or 404 if the request_id is unknown or not owned by your account.
Add "webhook_url": "https://your-server.com/cb" to the submit body. We POST the result to that URL once the job reaches a terminal state. Payload format:
json// On success (COMPLETED → status "OK")
{
"request_id": "c546...",
"status": "OK",
"payload": { "generated_images": [{ "url": "https://..." }] },
"error": null
}
// On failure (FAILED → status "ERROR")
{
"request_id": "c546...",
"status": "ERROR",
"payload": null,
"error": "<error description>"
}status fields — by design. The status endpoint returns the 5-value lifecycle enum (IN_QUEUE / IN_PROGRESS / COMPLETED / FAILED / CANCELLED). The webhook body uses the 2-value 2-value success enum (OK / ERROR) because webhooks fire only on terminal states and a binary outcome is all the receiver needs. Webhooks are not sent on CANCELLED (you initiated it, no notification needed).Webhook security: the URL must be HTTPS and resolve to a public IP (loopback / RFC1918 / link-local / metadata addresses are rejected at submit time as an SSRF guard). Delivery is best-effort with one retry; have your endpoint be idempotent on request_id.
COMPLETED — FAILED and CANCELLED jobs incur no charge.Endpoint
| Method | POST |
| URL | https://api.skillboss.co/v1/run |
| Auth header | Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY |
| Content-Type | application/json |
| Streaming | No SSE streaming, but supports async submit (set `"async": true`) which is the recommended path for long jobs — see the Async mode section. |
Errors
The API uses standard HTTP status codes:
Pricing
Wholesale pricing is your account-specific discount × vendor list price. Discount rate depends on your contract — see the live numbers on the wholesale dashboard. The dashboard shows your current cost per 1M tokens (or per image / per second) for every model.
No platform markup on standard token billing. Volume tiers + monthly caps are configurable per key.