Put the studio
inside your pipeline.
A single HTTP interface across every image, video and music model. Submit a job, poll or receive a webhook, and read the result — with the credit cost returned on every response.
Private beta. The public API and self-serve API keys are rolling out to Studio accounts. The shapes below are stable and safe to build against — request access and we will enable keys on your account.
Overview
The API is REST over HTTPS with JSON bodies. Every path is prefixed with /api. Generation is asynchronous: you submit a job, get an id back immediately, then either poll the status endpoint or let a webhook tell you when it is done.
https://api.ideovex.com,/api
Provider identity is deliberately never exposed. Media is served through Ideovex proxy URLs, so results keep working even if we move a model between providers.
Authentication
Send your API key as a bearer token on every request. Keys are scoped per environment, can be rotated without downtime, and carry their own rate limit.
curl https://api.ideovex.com/api/models/catalog \ -H "Authorization: Bearer $IDEOVEX_API_KEY"
Never ship a key in a browser bundle or mobile binary. Call the API from your own server and proxy the result to your client.
Generations
/api/generate/imageSubmit an image job/api/generate/videoSubmit a video job/api/generate/musicSubmit a music job/api/generate/status/{id}Poll an image / video job/api/generate/music/status/{id}Poll a music job/api/generationsList your generations/api/generations/{id}Delete a generationSubmitting a job
{
"prompt": "a weathered brass diving helmet half-buried in wet sand,
grey Atlantic beach at first light, 85mm, soft overcast light",
"model": "mdl_nano_banana_pro",
"aspect_ratio": "3:2",
"num_images": 2
}{
"generation_id": "gen_4ab482abb371",
"status": "processing",
"credits_used": 10,
"queue_position": 1
}Polling for the result
{
"generation_id": "gen_4ab482abb371",
"status": "completed",
"type": "image",
"credits_used": 10,
"result_url": "/api/media/image/gen_4ab482abb371",
"all_results": [
"/api/media/image/gen_4ab482abb371?i=0",
"/api/media/image/gen_4ab482abb371?i=1"
]
}Poll no faster than once every two seconds. status moves through queued → processing → completed, or lands on failed / timed_out — both of which refund the reserved credits automatically.
Video and music
Video accepts duration, resolution and an optional image_url for image-to-video models. Music accepts lyrics, style, title and instrumental, and is submitted to /api/generate/music then polled at /api/generate/music/status/{id}. Which fields a model honours is described on its catalogue entry.
Model catalogue
Always read the catalogue rather than hardcoding model ids — models are added, retired and health-gated continuously, and hidden models are filtered out of this response for you.
{
"image": [
{
"id": "mdl_nano_banana_pro",
"name": "Nano Banana Pro",
"cost": 5,
"free": false,
"mode": "t2i",
"needs_image": false,
"resolutions": ["1024x1024", "1024x1536", "1536x1024"]
}
],
"video": [ /* … */ ],
"music": [ /* … */ ]
}Credits
/api/user/creditsCurrent balance/api/user/quotaDaily quota state/api/user/concurrencySlots in use/api/pricingPublic cost tableCheck /api/user/concurrency before firing a batch. If no slot is free the job queues rather than erroring, but knowing the slot count lets you pace your own fan-out sensibly.
Webhooks
Rather than polling, register a callback URL in the studio under Developer → Webhooks and receive a POST the moment a job reaches a terminal state. Registration returns a whsec_ signing secret once — store it. Respond 2xx within ten seconds; we attempt delivery up to three times.
{
"event": "generation.completed",
"timestamp": "2026-06-15T09:12:44Z",
"data": {
"generation_id": "gen_4ab482abb371",
"type": "image",
"status": "completed",
"result_url": "/api/media/image/gen_4ab482abb371"
}
}Events: generation.started, generation.completed, generation.failed, generation.cancelled (or * for all). Each terminal event fires exactly once per generation.
Verifying the signature
Every request carries X-Webhook-Signature: sha256=<hex>, plus X-Webhook-Event and X-Webhook-Id. The signature is an HMAC-SHA256 of the raw request body keyed by your whsec_ secret. Compare it against the raw bytes you received — never against a re-serialised object — and reject anything that does not match.
import crypto from "crypto";
app.post("/hooks/ideovex", express.raw({ type: "application/json" }), (req, res) => {
const sig = (req.header("X-Webhook-Signature") || "").replace("sha256=", "");
const expected = crypto.createHmac("sha256", process.env.IDEOVEX_WEBHOOK_SECRET)
.update(req.body) // req.body is the raw Buffer
.digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.status(400).send("bad signature");
const { event, data } = JSON.parse(req.body);
// data.result_url is ready — no need to poll
res.sendStatus(200);
});Errors & rate limits
Errors are JSON with a stable HTTP status. The message is safe to log but not to show to end users verbatim.
{
"detail": "Rate limit exceeded. Retry after 12s."
}| Status | Meaning | What to do |
|---|---|---|
400 | Invalid or unavailable model / bad parameters | Re-read the catalogue |
401 | Missing or revoked key | Rotate the key |
402 | Not enough credits | Top up, then retry |
403 | Account not verified, or scope missing | Check key scopes |
429 | Rate or quota limit hit | Back off using the headers |
503 | Upstream capacity unavailable | Retry with jitter |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Drive your backoff from those rather than from a fixed sleep, and always add jitter when you retry.
Idempotency
Send an X-Idempotency-Key header on submissions. A repeat of the same key inside twenty-four hours returns the original generation instead of charging twice — the safe way to retry after a network error.
Getting access
Two steps to a key.
API keys are enabled per account while the API is in private beta.
Tell us the use case
Volume, output type and where the generation sits in your product. One paragraph is enough.
We enable keys
Keys appear in the studio under API Keys, scoped and rate-limited to your plan.
Build against the shapes above
They are stable. Anything that changes before general availability is announced in the changelog.
Request API access
Tell us what you are building and we will turn keys on for your account.