Cheaper Gen.

Reference

API reference

REST API reference: submit, poll and cancel generations, list models and prices, get quotes, read your balance and upload images, video and audio — with examples.

The API is organized around a few resources: generations (the jobs you run), models (what you can run and what it costs), quotes, your account and uploads. All requests and responses are JSON over HTTPS.

Base URLhttps://cheapergen.com/api/v1

Authenticate with Authorization: Bearer cg_live_… (see Authentication). Errors use the format described in Errors. All endpoints send CORS headers; never expose your key in a browser, though — only the public endpoints are meant to be called client-side.

API endpoints
Endpoint
POST/run/{endpoint}
GET/generations/{id}
GET/generations
POST/generations/{id}/cancel
DELETE/generations/{id}
GET/models
GET/models/{vendor}/{model}
POST/quote/{endpoint}
GET/account
POST/uploads

Submit a generation#

POST/api/v1/run/{endpoint}API key required

Starts an asynchronous generation and returns 202 Accepted with a generation object in the queued state. The price is held from your balance at this point (see Billing).

Path parameters
endpointstringrequired
The model endpoint ID, {vendor}/{model}/{task} — for example bytedance/seedance-2.0-fast/text-to-video. All IDs are listed on the Models page.
Body
…model inputsobjectrequired
The input fields of the endpoint, such as prompt, resolution or image_url. Each model's fields, types, defaults and allowed values are documented on its API page and returned as JSON Schema by Get a model. Unknown fields are rejected.
webhook_urlstring (https URL)
Optional. We POST the finished generation to this URL. See Webhooks.
retentionstring
Optional. How long we keep this generation's prompt, inputs and outputs: immediate, 1h, 1d, 7d or 30d. Defaults to your account's setting (1d). Any account can shorten it; 7d and 30d need an enterprise retention setting. See Data retention.
curl -X POST https://cheapergen.com/api/v1/run/bytedance/seedance-2.0-fast/text-to-video \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "A slow dolly-in on a ceramicist shaping a vase at golden hour, dust in the light, shallow depth of field",
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "duration": 5
}'
Response · 202 Accepted
{
  "id": "gen_8c2QmX1nq0k4Lw7Z",
  "object": "generation",
  "model": "bytedance/seedance-2.0-fast",
  "endpoint": "bytedance/seedance-2.0-fast/text-to-video",
  "mode": "text-to-video",
  "status": "queued",
  "input": {
    "prompt": "A slow dolly-in on a ceramicist shaping a vase at golden hour, dust in the light, shallow depth of field",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 5,
    "generate_audio": true
  },
  "output": null,
  "error": null,
  "cost": {
    "amount_usd": 0.3278,
    "currency": "usd",
    "estimated": true
  },
  "source": "api",
  "created_at": "2026-10-15T09:21:04.512Z",
  "started_at": null,
  "completed_at": null,
  "retention": "1d",
  "expires_at": null,
  "purged_at": null,
  "urls": {
    "get": "https://cheapergen.com/api/v1/generations/gen_8c2QmX1nq0k4Lw7Z",
    "cancel": "https://cheapergen.com/api/v1/generations/gen_8c2QmX1nq0k4Lw7Z/cancel"
  }
}

Errors: 400 invalid_request (validation), 401 unauthorized, 402 insufficient_balance, 404 not_found (unknown endpoint), 429 rate_limited (rate or concurrency limit), 503 model_unavailable.

Get a generation#

GET/api/v1/generations/{id}API key required

Returns a generation by ID. If a status check is due, it is performed before responding, so polling this endpoint is all you need to drive a job to completion. Returns 404 not_found for unknown IDs and for generations that belong to another account.

Request
curl https://cheapergen.com/api/v1/generations/gen_8c2QmX1nq0k4Lw7Z \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY"
Response · 200 OK
{
  "id": "gen_8c2QmX1nq0k4Lw7Z",
  "object": "generation",
  "model": "bytedance/seedance-2.0-fast",
  "endpoint": "bytedance/seedance-2.0-fast/text-to-video",
  "mode": "text-to-video",
  "status": "succeeded",
  "input": {
    "prompt": "A slow dolly-in on a ceramicist shaping a vase at golden hour, dust in the light, shallow depth of field",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 5,
    "generate_audio": true
  },
  "output": {
    "video": {
      "url": "https://cdn.cheapergen.ai/outputs/gen_8c2QmX1nq0k4Lw7Z.mp4",
      "content_type": "video/mp4"
    }
  },
  "error": null,
  "cost": {
    "amount_usd": 0.3278,
    "currency": "usd",
    "estimated": false
  },
  "source": "api",
  "created_at": "2026-10-15T09:21:04.512Z",
  "started_at": "2026-10-15T09:21:09.031Z",
  "completed_at": "2026-10-15T09:22:31.870Z",
  "retention": "1d",
  "expires_at": "2026-10-16T09:22:31.870Z",
  "purged_at": null
}

List generations#

GET/api/v1/generationsAPI key required

Lists your generations, newest first. Includes jobs submitted from the Studio and playgrounds.

Query parameters
limitinteger
Page size, 1–100. Default 20.
cursorstring
The next_cursor from the previous page.
statusstring
Only return generations with this status: queued, running, succeeded, failed or canceled.
modelstring
Only return generations for this model ID, e.g. bytedance/seedance-2.0-fast.
Request
curl "https://cheapergen.com/api/v1/generations?limit=2&status=succeeded" \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY"
Response · 200 OK
{
  "object": "list",
  "data": [
    {
      "id": "gen_8c2QmX1nq0k4Lw7Z",
      "object": "generation",
      "model": "bytedance/seedance-2.0-fast",
      "endpoint": "bytedance/seedance-2.0-fast/text-to-video",
      "mode": "text-to-video",
      "status": "succeeded",
      "input": {
        "prompt": "A slow dolly-in on a ceramicist shaping a vase at golden hour, dust in the light, shallow depth of field",
        "aspect_ratio": "16:9",
        "resolution": "720p",
        "duration": 5,
        "generate_audio": true
      },
      "output": {
        "video": {
          "url": "https://cdn.cheapergen.ai/outputs/gen_8c2QmX1nq0k4Lw7Z.mp4",
          "content_type": "video/mp4"
        }
      },
      "error": null,
      "cost": {
        "amount_usd": 0.3278,
        "currency": "usd",
        "estimated": false
      },
      "source": "api",
      "created_at": "2026-10-15T09:21:04.512Z",
      "started_at": "2026-10-15T09:21:09.031Z",
      "completed_at": "2026-10-15T09:22:31.870Z",
      "retention": "1d",
      "expires_at": "2026-10-16T09:22:31.870Z",
      "purged_at": null
    },
    {
      "id": "gen_3vYk2PqL9sTn0bWd",
      "object": "generation",
      "model": "bytedance/seedream-5.0-pro",
      "endpoint": "bytedance/seedream-5.0-pro/text-to-image",
      "mode": "text-to-image",
      "status": "succeeded",
      "input": {
        "prompt": "Editorial product photo of a matte-black espresso machine on travertine, soft window light, 85mm",
        "aspect_ratio": "1:1",
        "size": "2K"
      },
      "output": {
        "images": [
          {
            "url": "https://cdn.cheapergen.ai/outputs/gen_8c2QmX1nq0k4Lw7Z.png",
            "content_type": "image/png"
          }
        ]
      },
      "error": null,
      "cost": {
        "amount_usd": 0.0542,
        "currency": "usd",
        "estimated": false
      },
      "source": "api",
      "created_at": "2026-10-15T09:21:04.512Z",
      "started_at": "2026-10-15T09:21:09.031Z",
      "completed_at": "2026-10-15T09:22:31.870Z",
      "retention": "1d",
      "expires_at": "2026-10-16T09:22:31.870Z",
      "purged_at": null
    }
  ],
  "next_cursor": "gen_3vYk2PqL9sTn0bWd"
}

next_cursor is null on the last page.

Cancel a generation#

POST/api/v1/generations/{id}/cancelAPI key required

Cancels a generation that is still queued and refunds its hold in full. Returns the updated generation with status: "canceled". Returns 409 conflict if the generation is already running or finished, or if the model does not support canceling queued jobs.

Request
curl -X POST https://cheapergen.com/api/v1/generations/gen_8c2QmX1nq0k4Lw7Z/cancel \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY"
Response · 200 OK
{
  "id": "gen_8c2QmX1nq0k4Lw7Z",
  "object": "generation",
  "model": "bytedance/seedance-2.0-fast",
  "endpoint": "bytedance/seedance-2.0-fast/text-to-video",
  "mode": "text-to-video",
  "status": "canceled",
  "input": {
    "prompt": "A slow dolly-in on a ceramicist shaping a vase at golden hour, dust in the light, shallow depth of field",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 5,
    "generate_audio": true
  },
  "output": null,
  "error": null,
  "cost": {
    "amount_usd": 0,
    "currency": "usd",
    "estimated": false
  },
  "source": "api",
  "created_at": "2026-10-15T09:21:04.512Z",
  "started_at": null,
  "completed_at": "2026-10-15T09:21:06.200Z",
  "retention": "1d",
  "expires_at": "2026-10-16T09:21:06.200Z",
  "purged_at": null
}

Delete a generation#

DELETE/api/v1/generations/{id}API key required

Deletes a finished generation: its output files, the uploaded inputs no other generation uses, the prompt and the input are removed immediately, it no longer appears in lists, and GET returns 404. Billing records (the charge in your ledger and usage totals) are kept. Returns 409 conflict while the generation is queued or running — cancel it or wait for it to finish first.

Request
curl -X DELETE https://cheapergen.com/api/v1/generations/gen_8c2QmX1nq0k4Lw7Z \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY"
Response · 200 OK
{
  "id": "gen_8c2QmX1nq0k4Lw7Z",
  "object": "generation",
  "deleted": true
}

The generation object#

idstring
Unique ID, prefixed gen_.
objectstring
Always "generation".
modelstring
Model ID, e.g. bytedance/seedance-2.0-fast.
endpointstring
Endpoint ID the job was submitted to, e.g. bytedance/seedance-2.0-fast/text-to-video.
modestring
Task: text-to-video, image-to-video, reference-to-video, text-to-image or image-edit.
statusstring
queued → running → succeeded | failed, or canceled. See Generations.
inputobject
The validated input, with defaults filled in.
outputobject | null
Set on success. Video: { "video": { "url", "content_type" } }. Image: { "images": [{ "url", "content_type" }] }.
errorobject | null
Set on failure: { "code", "message" }. See failure codes.
costobject
amount_usd, currency ("usd") and estimated — true while the amount is a hold, false once final. Failed and canceled generations cost 0.
sourcestring
"api" or "playground" (Studio and model pages).
created_atstring
ISO 8601 timestamp of submission.
started_atstring | null
When the model started generating.
completed_atstring | null
When the generation reached a final state.
retentionstring | null
API generations: immediate, 1h, 1d, 7d or 30d. null for Studio generations, which are kept until you delete them.
expires_atstring | null
When the content (prompt, inputs, outputs, media) is deleted. Set when the generation finishes. With immediate it is moved to 10 minutes after the result is first delivered.
purged_atstring | null
Set once the content was deleted. output is then null, input keeps only the parameters that set the price, and content_expired explains why. Cost and timestamps stay.
urlsobject
Only on the submit response: get and cancel URLs for this generation.

List models#

GET/api/v1/modelsPublic · no auth

Returns every available model with its endpoints and live pricing. Prices are per unit (second of video or image); list_price_usd is the official list price and discount_pct the saving in percent.

Request
curl https://cheapergen.com/api/v1/models
Response · 200 OK
{
  "object": "list",
  "data": [
    {
      "id": "bytedance/seedance-2.0-fast",
      "object": "model",
      "name": "Seedance 2.0 Fast",
      "vendor": "ByteDance",
      "category": "video",
      "available": false,
      "url": "https://cheapergen.com/models/bytedance/seedance-2.0-fast",
      "endpoints": [
        {
          "id": "bytedance/seedance-2.0-fast/text-to-video",
          "mode": "text-to-video",
          "output": "video"
        },
        {
          "id": "bytedance/seedance-2.0-fast/image-to-video",
          "mode": "image-to-video",
          "output": "video"
        },
        {
          "id": "bytedance/seedance-2.0-fast/reference-to-video",
          "mode": "reference-to-video",
          "output": "video"
        }
      ],
      "pricing": {
        "unit": "second",
        "tiers": [
          {
            "tier": "480p",
            "price_usd": 0.0305,
            "list_price_usd": 0.056246,
            "discount_pct": 46
          },
          {
            "tier": "720p",
            "price_usd": 0.06556,
            "list_price_usd": 0.12096,
            "discount_pct": 46
          }
        ]
      }
    }
  ]
}

Truncated to one model for brevity.

Get a model#

GET/api/v1/models/{vendor}/{model}Public · no auth

Returns one model with a JSON Schema for each endpoint's input — useful for building forms or validating requests before you send them. Returns 404 not_found for unknown models.

Request
curl https://cheapergen.com/api/v1/models/bytedance/seedream-5.0-pro
Response · 200 OK
{
  "id": "bytedance/seedream-5.0-pro",
  "object": "model",
  "name": "Seedream 5.0 Pro",
  "vendor": "ByteDance",
  "category": "image",
  "available": false,
  "description": "ByteDance Seedream 5.0 Pro creates and edits photorealistic, on-brand images up to 2K with precise multi-image editing and accurate text rendering.",
  "url": "https://cheapergen.com/models/bytedance/seedream-5.0-pro",
  "endpoints": [
    {
      "id": "bytedance/seedream-5.0-pro/text-to-image",
      "mode": "text-to-image",
      "label": "Text to Image",
      "output": "image",
      "input_schema": {
        "type": "object",
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "title": "Prompt",
            "description": "Describe the shot: subject, action, camera movement, lighting and style.",
            "type": "string",
            "maxLength": 5000
          },
          "aspect_ratio": {
            "title": "Aspect ratio",
            "description": "Output image shape.",
            "type": "string",
            "enum": [
              "1:1",
              "4:3",
              "3:4",
              "16:9",
              "9:16",
              "3:2",
              "2:3",
              "21:9"
            ],
            "default": "1:1"
          },
          "size": {
            "title": "Size",
            "description": "1K ≈ 1 megapixel, 2K ≈ 4 megapixels.",
            "type": "string",
            "enum": [
              "1K",
              "2K"
            ],
            "default": "2K"
          },
          "seed": {
            "title": "Seed",
            "description": "Use the same seed and settings to reproduce a result. Leave empty for random.",
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "title": "Webhook URL",
            "description": "Optional. We POST the finished generation here (signed)."
          }
        },
        "additionalProperties": false
      }
    }
  ],
  "pricing": {
    "unit": "image",
    "notes": [],
    "tiers": [
      {
        "tier": "1K",
        "detail": "≈1 MP",
        "price_usd": 0.0271,
        "list_price_usd": 0.045,
        "discount_pct": 40
      },
      {
        "tier": "2K",
        "detail": "≈4 MP",
        "price_usd": 0.0542,
        "list_price_usd": 0.09,
        "discount_pct": 40
      }
    ]
  }
}

Truncated to one endpoint for brevity.

Get a quote#

POST/api/v1/quote/{endpoint}Public · no auth

Prices an input without running it. Only price-relevant fields (resolution, duration, size, number of images…) are read; content fields such as prompt and reference URLs are ignored, and omitted fields use their defaults. available is false if the model is temporarily not accepting generations.

Reference videos add billed seconds. To include them, pass reference_video_durations (seconds, one number per clip) — an estimate hint; /run measures the real files and holds that price. See Billing.

Request
curl -X POST https://cheapergen.com/api/v1/quote/bytedance/seedance-2.0-fast/text-to-video \
  -H "Content-Type: application/json" \
  -d '{"aspect_ratio":"16:9","resolution":"720p","duration":5}'
Response · 200 OK
{
  "amount_usd": 0.3278,
  "list_usd": 0.6048,
  "discount_pct": 46,
  "available": false,
  "currency": "usd"
}

Get your account#

GET/api/v1/accountAPI key required

Returns your balance and auto top-up settings. balance_usd is spendable now; reserved_usd is held by in-flight generations. See Billing & credits.

Request
curl https://cheapergen.com/api/v1/account \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY"
Response · 200 OK
{
  "object": "account",
  "email": "you@company.com",
  "balance_usd": 42.5,
  "reserved_usd": 1.2,
  "auto_topup": {
    "enabled": true,
    "threshold_usd": 10,
    "amount_usd": 50
  }
}

Upload a file#

POST/api/v1/uploadsAPI key required

Uploads a file you can pass as an input URL — a first frame, a reference image, a reference video or a reference audio clip. You can also pass any public HTTPS URL directly instead of uploading.

KindTypesMax size
ImagePNG, JPEG, WebP, GIF20 MB
VideoMP4, MOV50 MB
AudioMP3, WAV, M4A (models currently take MP3 or WAV)15 MB

Direct upload (recommended)#

Send JSON with the file's filename, content_type and size in bytes. You get back a short-lived upload_url; PUT the raw bytes to it with exactly the returned headers, then use url as the input. The file goes straight to storage, so there is no request-size limit beyond the ones above. The upload URL expires after 15 minutes.

Request
curl -X POST https://cheapergen.com/api/v1/uploads \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename":"choreo.mp4","content_type":"video/mp4","size":8421903}'
Response · 201 Created
{
  "object": "upload",
  "method": "PUT",
  "upload_url": "https://storage.example.com/media/uploads/7f3k2m9q/0b8d2c5e1a7f4h6j9k3m.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&…",
  "headers": {
    "Content-Type": "video/mp4"
  },
  "url": "https://cdn.cheapergen.ai/uploads/7f3k2m9q/0b8d2c5e1a7f4h6j9k3m.mp4",
  "kind": "video",
  "content_type": "video/mp4",
  "bytes": 8421903,
  "expires_at": "2026-10-15T09:36:04.000Z"
}
Then upload the bytes
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: video/mp4" \
  --data-binary @choreo.mp4

Multipart upload#

Alternatively send multipart/form-data with a file field and we store it for you (201 Created with url). This proxies the bytes through our API, where request bodies are limited to about 4.5 MB — use direct upload for anything larger. If direct upload isn't available on a deployment, the JSON request returns 501 direct_upload_unavailable; fall back to multipart.

Request
curl -X POST https://cheapergen.com/api/v1/uploads \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY" \
  -F "file=@first-frame.png"
Response · 201 Created
{
  "object": "upload",
  "url": "https://cdn.cheapergen.ai/uploads/7f3k2m9q/0b8d2c5e1a7f4h6j9k3m.png",
  "kind": "image",
  "content_type": "image/png",
  "bytes": 1834221
}

Using an uploaded image#

Pass the returned URL in the image field of an image-to-video or edit endpoint:

curl -X POST https://cheapergen.com/api/v1/run/bytedance/seedance-2.0-fast/image-to-video \
  -H "Authorization: Bearer $CHEAPERGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "The camera pushes in as she turns and smiles; hair moves in the wind",
  "image_url": "https://cdn.cheapergen.ai/uploads/7f3k2m9q/0b8d2c5e1a7f4h6j9k3m.png",
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "duration": 5
}'

Per-model reference

Every model has its own API page with each field's type, default and allowed values, plus copy-paste examples — start from the model list.

Something unclear or missing? Email support@cheapergen.com — we read everything.