Generations API Reference

Complete documentation for the ModelStack Generations API — create, list, and manage AI-generated images and videos.

Overview

The Generations API provides a unified interface for AI image and video generation across multiple providers. All requests require authentication with an API key.

Base URL

https://api.modelstack.cc

Authentication

Include your API key in the Authorization header:

Authorization: Bearer sk_YOUR_API_KEY

Rate Limits

There is currently no enforced rate limit on the Generations API — don't build against a specific requests-per-minute figure. Your effective throughput is bounded by your account balance, since every generation is billed on creation.

POST

Create Generation

/v1/generations

Create a new image or video generation. Returns immediately with a pending generation — poll the generation ID to get the result.

Request Body

FieldTypeRequiredDescription
typestringYesGeneration type, e.g. TEXT_TO_IMAGE, TEXT_TO_VIDEO, IMAGE_TO_IMAGE
promptstringYesText prompt describing the desired output
modelstringYesModel identifier, e.g. google/nano-banana-2-lite
modelSettingsobjectNoModel-specific parameters (aspect ratio, resolution, duration, etc.)
curl -X POST "https://api.modelstack.cc/v1/generations" \
  -H "Authorization: Bearer sk_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "TEXT_TO_IMAGE",
    "prompt": "A serene mountain landscape at sunset",
    "model": "google/nano-banana-2-lite",
    "modelSettings": {
      "aspect_ratio": "16:9"
    }
  }'

Response

{ "data": { "id": "gen_abc123" } }

Only the id is returned — poll GET /v1/generations/{id} for status and output.

GET

Get Generation

/v1/generations/{id}

Get the status and result of a specific generation. Poll this endpoint to check when generation is complete.

curl "https://api.modelstack.cc/v1/generations/gen_abc123" \
  -H "Authorization: Bearer sk_YOUR_API_KEY"

Response

{
  "data": {
    "id": "gen_abc123",
    "status": "completed",
    "creditsUsed": 40,
    "outputMediaUrls": ["media/user_123/gen_abc123/0.png"],
    "createdAt": "2026-01-01T00:00:00.000Z",
    "completedAt": "2026-01-01T00:00:12.000Z"
  }
}

status is one of pending, processing, completed, failed, or deleted.outputMediaUrls holds storage keys, not downloadable URLs — exchange each key for a signed URL via GET /v1/media/presigned-url?key=... (expires after 1 hour).

GET

List Generations

/v1/generations

List all generations with pagination and optional status filtering.

Query Parameters

ParameterTypeDefaultDescription
limitnumberNoMax records (max 100)(default: 25)
offsetnumberNoPagination offset(default: 0)
statusstringNoFilter: pending | processing | completed | failed
curl "https://api.modelstack.cc/v1/generations?limit=10&status=completed" \
  -H "Authorization: Bearer sk_YOUR_API_KEY"
DELETE

Delete Generation

/v1/generations/{id}

Delete a completed or failed generation to free up storage.

curl -X DELETE "https://api.modelstack.cc/v1/generations/gen_abc123" \
  -H "Authorization: Bearer sk_YOUR_API_KEY"

Response

{ "success": true }

Error Handling

Error responses are not uniformly shaped — the shape depends on which layer rejects the request.

Rejected before reaching the app

Auth failures and insufficient-balance pre-checks return a nested shape:

{ "error": { "message": "Authentication failed", "type": "invalid_api_key" } }

HTTP 401.

{
  "error": { "message": "Insufficient balance", "type": "insufficient_balance", "code": "insufficient_balance" },
  "balance": { "available": 0, "required": 10000 }
}

HTTP 402. This pre-check uses a rough flat cost estimate, not the exact per-request price — it can pass and still have the real balance check fail later (surfacing as a 500, see below).

Rejected by the app

Validation/lookup failures once the request reaches the app return a flat string, not a nested object:

{ "error": "type, prompt, and model are required" }

HTTP 400. Similarly, { "error": "Unauthorized" } for 401, and { "error": "<message>" } for 404.

Known edge-case behavior

  • GET /v1/generations/{id} for a nonexistent id returns HTTP 200 with { "data": null }, not a 404.
  • DELETE /v1/generations/{id} on a pending/processing generation returns HTTP 500, not a 400 — only completed/failed generations can be deleted.
  • Unexpected failures (including the real balance check failing after the pre-check estimate passed) return { "error": "Internal server error" } (500) rather than a specific 4xx.