Generations
Start one, wait for it, read the result, cancel or delete it.
A generation is one order: a model, its input, and what came of it.
Start one
POST /v1/generations| Field | Needed | What it is |
|---|---|---|
model | Yes | A model id from GET /v1/models |
input | Yes | What to make. Its fields depend on the model: read its input_schema |
input.prompt | Yes | Up to 10,000 characters |
end_user | No | Your own id for your customer. A pseudonym, never an email |
metadata | No | Your notes, strings up to 500 characters. They come back with the generation |
retention_hours | No | Remove results sooner than the default 7 days: 1 to 168 |
Fields of input that a model can take: aspect_ratio, resolution, quality, output_format, duration, reference_mode, images, videos, audios. An unknown field is refused, not ignored.
Headers:
| Header | What it does |
|---|---|
Idempotency-Key | Recommended always. See Idempotency |
Prefer: wait=60 | Holds the call until it's done, up to that many seconds, 60 at most |
The price is charged now. The answer is 202 with a generation to poll, or 200 if it finished within your Prefer: wait.
Response headers:
| Header | What it says |
|---|---|
X-Credits-Charged | Credits this call took: the price on a new live generation, 0 on a repeat and on a test key |
Idempotent-Replayed | true when this is a repeat of an earlier request |
X-Request-Id | Always. Quote it if you contact us |
Follow it
GET /v1/generations/{id}queued -> running -> succeeded
-> failed (credits back)
-> canceled (credits back)Poll every poll_after_ms, which is 3 seconds today. It's only there while the generation is in progress.
The result
{
"id": "gen_01a1b37b65dc7dcd8c060f296add5cf8",
"object": "generation",
"model": "muse-video",
"status": "succeeded",
"mode": "live",
"price": { "credits": 2, "usd": "0.02", "charged": true },
"params": {},
"outputs": [
{
"type": "video",
"url": "https://cdn.nocamclub.com/api/8f3c…/1.mp4",
"content_type": "video/mp4",
"bytes": 1932156,
"width": 768,
"height": 1152,
"duration_seconds": 10,
"has_audio": true,
"expires_at": "2026-11-14T00:55:00.000Z"
}
],
"error": null,
"recovered": false,
"purged": false,
"timing": { "total_ms": 72000 },
"urls": { "self": "https://api.nocamclub.com/v1/generations/gen_01a1b37b65dc7dcd8c060f296add5cf8" },
"created_at": "2026-11-07T00:54:00.000Z",
"finished_at": "2026-11-07T00:55:12.000Z"
}- A photo or video output has a
url. A text output hastextinstead:{ "type": "text", "text": "…" }. paramsshows the settings it ran with, defaults filled in.price.chargedisfalseonce the credits have come back, and always on a test key.
When it fails
status is failed, error.message says why, error.hint what to do, and error.retryable whether the same request can work (send it with a new Idempotency-Key). The credits are already back. With Prefer: wait this still answers 200, so check status. See Errors.
{
"status": "failed",
"error": {
"code": "provider_unavailable",
"message": "No route can run this model right now. Your credits came back. Try again in a few minutes.",
"hint": "Try the same request in a few minutes, or another model.",
"retryable": true,
"docs_url": "https://docs.nocamclub.com/errors/provider_unavailable"
}
}A late result isn't lost. If a model finishes after we stopped waiting, we keep checking for a day. If it comes, the generation turns to succeeded with recovered: true, and you keep the refund.
List them
GET /v1/generations?status=succeeded&model=gpt-image-2&limit=20&cursor=…Newest first. has_more and next_cursor page through. You see only your own account's, in the key's mode.
Cancel one
POST /v1/generations/{id}/cancelWorks while no model has it yet, and the credits come back. After that it answers not_cancelable: the generation finishes and is billed.
Delete one
DELETE /v1/generations/{id}Removes the files and the prompt now, without waiting for them to expire. Only finished generations: otherwise not_finished.