Image Generation

Reve Text-to-Image API

Reve Text-to-Image — versatile general-purpose image generation. Pass `prompt` (and optional `aspect_ratio`) to `inputs`. Output is returned as `images[].url`. Set HTTP client timeout ≥ 120s.

model: reve/text-to-image
Wholesale key required. This endpoint accepts wholesale keys only. Have access? Get your key on the wholesale dashboard. Not on wholesale yet? Email admin@skillboss.co with your use case — we'll get you provisioned.

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": "reve/text-to-image",
    "async": true,
    "inputs": {
      "prompt": "A premium commercial advertising photo of a coffee cup, studio lighting, white background",
      "size": "1024x1024",
      "output_format": "png"
    }
  }'
# → {"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_KEY

Treat 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

Python
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": "reve/text-to-image",
        "async": True,
        "inputs": {
            "prompt": "A premium commercial advertising photo of a coffee cup, studio lighting, white background",
            "size": "1024x1024",
            "output_format": "png",
        },
    },
    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)
JavaScript / TypeScript
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: "reve/text-to-image",
    async: true,
    inputs: {
      prompt: "A premium commercial advertising photo of a coffee cup, studio lighting, white background",
      size: "1024x1024",
      output_format: "png",
    },
  }),
}).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.

NameTypeRequiredDescription
modelstringrequiredModel id. Use reve/text-to-image.
inputs.promptstringrequiredText description of the image to generate. For Gemini family (Nano Banana), prefer imperative phrasing ("Create a premium ad of …") over question/instruction phrasing — the thinking model is more likely to emit an image when asked imperatively.
asyncbooleanoptionalSet true to get a request_id + status_url back instantly and poll. Recommended for all image gen — NB Pro takes 10-60s, well past most HTTP timeouts.
webhook_urlstringoptionalHTTPS URL we POST the result to on completion. Implies async mode — no need to also set async: true.
inputs.sizestringoptionalResolution, e.g. 1024x1024, 1024x1792, 1792x1024. Defaults to 1024x1024.
inputs.nintegeroptionalNumber of images to generate in one call (1-4). Default 1.
inputs.output_formatstringoptionalOne of png (default), jpeg, webp.

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.

1. Submit (returns 202 immediately)
bashcurl -X POST https://api.skillboss.co/v1/run \
  -H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "reve/text-to-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.

2. Poll status (or use webhook — see below)
bashcurl https://api.skillboss.co/v1/run/status/{request_id} \
  -H "Authorization: Bearer $SKILLBOSS_WHOLESALE_KEY"

Status enum — the full lifecycle:

StatusMeaningTerminal?Billed?
IN_QUEUEJob accepted, awaiting worker pickup. Cancellable.nono
IN_PROGRESSWorker has claimed the job; vendor call in flight. Cancel returns 409 from here on.nono
COMPLETEDSuccess. result field contains generated_images / videos URLs.yesyes
FAILEDVendor error or insufficient balance. error field has details.yesno
CANCELLEDClient called the cancel endpoint while IN_QUEUE.yesno

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.

3. Cancel (optional — only effective while IN_QUEUE)
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.

4. Webhook (alternative to polling)

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>"
}
Two different 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.

Recommendation: Use async for any production workload where you don't want a 30–120s sync blocking call. Sync is fine for interactive testing. Billing rule: you're charged only on COMPLETED FAILED and CANCELLED jobs incur no charge.

Endpoint

MethodPOST
URLhttps://api.skillboss.co/v1/run
Auth headerAuthorization: Bearer $SKILLBOSS_WHOLESALE_KEY
Content-Typeapplication/json
StreamingNo 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:

200OKRequest succeeded.
400Bad RequestInvalid model, missing required field, or malformed JSON.
401UnauthorizedMissing or invalid wholesale key. Non-wholesale console keys are rejected here.
402Insufficient CreditsWholesale balance too low — top up on the wholesale dashboard.
429Rate LimitedToo many requests. Back off with exponential delay.
500Server ErrorTransient upstream issue. Safe to retry.
503Upstream UnavailableDiscount pool capacity issue (lite tier). Retry or fall back to standard tier.

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.