Studio Inference
BillingGet API key

API Reference

OpenAI-compatible. Use any OpenAI SDK by pointing it at our base URL.

On this page
AuthenticationService statusModel catalog/api/v1/llm/chat/api/v1/imggen/generate/api/v1/video/generateRate limitsError responsesWebhooksChangelog

Authentication

All endpoints require a Studio API key passed as a Bearer token:

Authorization: Bearer sk_live_<your_key>

Get a key from your Studio dashboard.

Keys carry scopes:

  • llm:read, llm:write — chat completions
  • imggen:read, imggen:write — image + video generation and status polling
  • training:read, training:write — fine-tuning jobs (coming soon)

Anonymous access is not permitted. 401 means key missing/invalid; 403 means key lacks the scope.

Service status

Live state of Studio Inference surfaces:

SurfaceStateNotes
POST /api/v1/llm/chatOKJessi VL 30B (Qwen3-VL-30B-A3B-Instruct, MoE) served via in-cluster vLLM. ~1.5s p50 first-token.
POST /api/v1/imggen/generate + statusOKz-image-pro and flux-krea via studio-cloud. ~80s end-to-end.
POST /api/v1/video/generate + statusOKStudio Video v2. ~2-5 min/clip.
GET /api/public/modelsOKPublic catalog (white-labeled).
Vision input on jessi-vlDEGRADEDCurrently text-only mode in deployment. We're re-enabling multimodal.

Model catalog

Browse models programmatically (no auth required):

curl https://api.yourjessi.com/api/public/models                    # all
curl 'https://api.yourjessi.com/api/public/models?category=llm'    # filter
curl 'https://api.yourjessi.com/api/public/models?vision=true'     # vision-capable

Response shape (vendor-redacted):

{
  "models": [
    {
      "slug": "jessi-vl",
      "label": "Jessi VL 30B (Qwen3-VL-30B-A3B)",
      "description": "Multimodal LLM (MoE 3B active). Currently text-only mode.",
      "category": "llm",
      "family": "multimodal",
      "accepts_vision": false,
      "vision_status": "degraded",
      "context_window": 32768,
      "tags": ["reasoning", "tool-use"],
      "pricing": { "unit": "token_per_1k", "input_per_1k": 0.0008, "output_per_1k": 0.0024 },
      "pool": "studio-llm",
      "status": "active"
    }
  ],
  "count": 10
}

POST /api/v1/llm/chat

OpenAI chat-completion shape. Streaming supported with stream: true.

curl -X POST https://api.yourjessi.com/api/v1/llm/chat \
  -H "Authorization: Bearer $STUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jessi-vl",
    "messages": [{"role":"user","content":"Hello!"}],
    "max_tokens": 256,
    "temperature": 0.7
  }'

Streaming

Pass stream: true. Response is SSE; final chunk is data: [DONE]:

{ "model": "jessi-vl", "messages": [...], "stream": true }

Vision input currently degraded

The API accepts OpenAI content-parts:

{
  "model": "jessi-vl",
  "messages": [{
    "role": "user",
    "content": [
      {"type":"text","text":"What's in this image?"},
      {"type":"image_url","image_url":{"url":"https://example.com/photo.jpg"}}
    ]
  }]
}

⚠ The current deployment is in text-only mode. image_url parts are accepted but the model will not interpret them. Tracking in the next deployment iteration.

OpenAI SDK

from openai import OpenAI

client = OpenAI(
    base_url="https://api.yourjessi.com/api/v1/llm",
    api_key="$STUDIO_API_KEY",
)
resp = client.chat.completions.create(
    model="jessi-vl",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.choices[0].message.content)

POST /api/v1/imggen/generate

Submit an async image generation job. Returns 202 with a job id; poll /api/v1/imggen/status/[id].

curl -X POST https://api.yourjessi.com/api/v1/imggen/generate \
  -H "Authorization: Bearer $STUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "z-image-pro",
    "prompt": "a green parrot perched on a branch"
  }'

Response (HTTP 202):

{
  "id": "57ae954c-7026-4e84-ba03-ee63e337bc01",
  "upstream_job_id": "ed988aae-d72d-4408-afa9-a774dee78b65-u1",
  "status": "queued",
  "model": "z-image-pro",
  "pool": "studio-cloud",
  "status_url": "/api/v1/imggen/status/57ae954c-7026-4e84-ba03-ee63e337bc01",
  "unit_type": "image",
  "price_per_unit": 0.012,
  "estimated_price": 0.012
}

Polling status

curl https://api.yourjessi.com/api/v1/imggen/status/$JOB_ID \
  -H "Authorization: Bearer $STUDIO_API_KEY"

Response when complete (HTTP 200):

{
  "id": "57ae954c-7026-4e84-ba03-ee63e337bc01",
  "model": "z-image-pro",
  "status": "complete",
  "output_url": "https://studio-bucket.yourjessi.com/u/<user>/2026/05/z-image-pro-...png",
  "output_urls": ["https://studio-bucket.yourjessi.com/..."],
  "pool": "studio-cloud"
}

Status values: queued, processing, complete, failed. Output images are persisted to public R2 storage and the URL is permanent. Typical end-to-end: 10-40s for image, 2-5min for video.

POST /api/v1/video/generate

Same shape as imggen, plus length_seconds and (optional) image_url for image-to-video:

curl -X POST https://api.yourjessi.com/api/v1/video/generate \
  -H "Authorization: Bearer $STUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "wan2-video",
    "prompt": "A cat playing in a sunbeam.",
    "length_seconds": 5,
    "image_url": "https://example.com/cat.jpg"
  }'

Status polling: GET /api/v1/video/status/[id] (same response shape as imggen).

Rate limits

Default: 300 requests per minute per key. Sliding 60-second window.

Every successful response carries:

X-RateLimit-Limit:     300
X-RateLimit-Remaining: 287
X-RateLimit-Reset:     1715520000   # unix epoch seconds

429 responses are not billed. Retry with exponential backoff. If you need a higher limit (production usage), contact us via your Studio dashboard.

Error responses

All errors return JSON of the shape:

{ "error": { "code": "invalid_model", "message": "Unknown LLM model 'foo'." } }

Common codes:

HTTPcodeCause
400invalid_jsonBody wasn't parseable JSON.
400invalid_requestRequired field missing or wrong type.
400invalid_modelUnknown model slug. See /api/public/models.
400wrong_endpointTried image model on /llm/chat or vice versa.
401unauthorizedBearer token missing/malformed/revoked.
403forbiddenKey lacks the required scope (e.g. llm:write).
429rate_limit_exceededKey over its requests-per-minute. Not billed.
502upstream_unreachableBackend (vLLM / RunPod) didn't respond. Retry; we autopage on >5min.
502upstream_errorBackend returned an error (HTTP 5xx, OOM, etc.).
503model_pausedModel is in maintenance. Try a different model in same family.
503provider_unavailablePool offline. Same as above.

Webhooks (coming soon)

For long-running image/video jobs, you'll be able to register a webhook URL on your dashboard. We'll POST { event, generation_id, status, output_url } on completion or failure with an HMAC-SHA256 signature in X-Studio-Signature.

Recent changes

  • 2026-05-13 — Public launch on api.yourjessi.com. LLM chat (text), image gen (z-image-pro, flux-krea), video gen (wan2-video) all live.
  • 2026-05-13 — Cluster control plane recovered after etcd quorum loss. vLLM serving Jessi VL 30B (Qwen3-VL-30B-A3B-Instruct, MoE) again.
  • 2026-05-13 — Catalog corrected: jessi-vl is the 30B MoE model, not 72B. The 72B yaml in repo is unused/aspirational.
  • Pending — Re-enable vision input on jessi-vl (deployment in text-only mode currently).
  • Pending — Webhooks, fine-tuning, custom domains.