API Documentation

Generate images, video, and audio programmatically with the ZOOOP REST API — auth, task submission, and polling, with cURL, JavaScript, and Python examples.

Overview

The ZOOOP REST API lets you generate images, video, and audio programmatically — the same models available in the ZOOOP web app, driven from your own code.

Prefer a terminal? The ZOOOP CLI wraps this API: npx zooop login signs you in through the browser, then zooop run submits, waits and downloads the result.

Base URL — every endpoint lives under https://zooop.ai/api/public/v1 (also reachable as https://api.zooop.ai/v1). The version (v1) is fixed in the path.

How it works — generation is asynchronous. You submit a task, then poll it until it reaches a terminal state:

  1. POST /tasks — submit a generation request and get back a taskId.
  2. GET /tasks/{id} — poll until status is succeeded, failed, or cancelled.
  3. Read the result from outputs[].url.

All responses are JSON. Authentication uses a Bearer API key — see Authentication.

Authentication

Every request must include your API key as a Bearer token:

Authorization: Bearer zpk_live_xxxxxxxx...

A key is shown in full only once, at creation — store it somewhere safe.

From a terminal — run zooop login (ZOOOP CLI). It opens the browser, you check the code and approve, and the CLI receives a key bound to the account and project you picked. These keys show a CLI badge on the API Keys page and can be revoked there like any other. See CLI sign-in.

Or create a key yourself. Personal and team keys are created in different places:

  • Personal keys bill against your personal credit balance. Create them on the API Keys page (user settings → API Keys).
  • Team keys bill against the team’s shared balance. They are created separately, inside the team admin panel — open Your teams, pick a team, and go to its API Keys tab. (Requires owner/admin role.)

Key properties — each key is bound to a project and can carry an optional expiry and a daily credit cap. Call GET /me to inspect a key’s remaining quota and rate limits.

Requests without a valid key return 401 (missing_token, invalid_token, user_not_found). A banned account, a key whose project was deleted, or a team key whose team is gone returns 403 (account_banned, token_project_unbound, team_unavailable).

curl https://zooop.ai/api/public/v1/me \
-H "Authorization: Bearer $ZOOOP_API_KEY"

Quickstart

Submit an image generation task and wait for the result.

From a terminal, the ZOOOP CLI does all of this in two commands: npx zooop login, then zooop run. To call the API from your own code:

  1. Get an API key and export it as ZOOOP_API_KEY — a personal key, or a team key from your team admin panel (see Authentication).
  2. Pick a model — call GET /api/public/v1/models to discover interfaceId / versionId pairs, or pass an aiTool / template slug instead.
  3. Submit the task, then poll until it finishes and read outputs[0].url.

The snippet on the right runs the full submit → poll → read-result loop.

# 1. Submit a task
curl -X POST https://zooop.ai/api/public/v1/tasks \
-H "Authorization: Bearer $ZOOOP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"interfaceId": "your-model-interface-id",
"versionId": "your-model-version-id",
"params": { "prompt": "a cinematic shot of a city at night" }
}'
# -> { "taskId": "abc123", "status": "queued", ... }
# 2. Poll until status is succeeded / failed / cancelled
curl https://zooop.ai/api/public/v1/tasks/abc123 \
-H "Authorization: Bearer $ZOOOP_API_KEY"

Errors & rate limits

All errors share the same JSON shape: an error object with message, type, and a stable machine-readable code (plus an optional param and extra fields).

type is one of authentication_error, permission_error, invalid_request_error, rate_limit_error, api_error.

Common codes

HTTPcodeMeaning
400invalid_payload / missing_required_params / param_out_of_domain / param_conflict / foreign_urlMalformed request or params. missing_required_params also returns error.params with the expected param definitions
401missing_token / invalid_token / user_not_foundMissing or invalid key
402arrearsBalance too low for this task, or negative
402token_daily_cap_exceededThis task would push the key past its daily credit cap (error.spent, error.cap, error.cost)
402team_subscription_inactive / viewer_seatTeam key: the team’s subscription lapsed, or the seat can’t generate
403account_banned / token_project_unbound / team_unavailable / model_not_publicAccount, key or model unusable
403team_banned / team_scheduled_for_deletion / team_storage_arrears / team_arrearsTeam key: the team is suspended
404unknown_model / unknown_ai_tool / unknown_template / unknown_task / unknown_uploadNot found (or not yours)
422moderation_blockedThe prompt violates the content policy (checked before any credits are charged)
422aspect_ratio_unsupported / image_format_unsupported / video_too_long / text_too_short / text_too_long / too_many_items / too_few_itemsAn input file or text doesn’t fit the model
429rate_limitedToo many requests — see Retry-After
429token_daily_cap_reachedThe key already spent its daily credit cap (error.spent, error.cap)
503pricing_misconfigured / vision_unavailable / moderation_unavailableTemporary server-side problem — retry later

Rate limits — applied per key, per 60-second window. Exceeding a limit returns 429 with a Retry-After header. GET /me returns the live numbers in limits.

EndpointLimit
POST /tasks, POST /tasks/{id}/cancel60 / min
POST /uploads30 / min
GET /tasks, GET /uploads/{id}, GET /me, POST /quote, GET /ai-tools, GET /templates120 / min each
POST /describe-image10 / min
GET /tasks/{id}, GET /modelsno fixed limit

ZOOOP CLI

Sign in from a terminal through the browser — no key to copy.

zooop login starts a login, shows a short code (like QBKF-7XRM) and opens zooop.ai/cli/login. Check that the browser shows the same code, pick whose credits to use and which project results go to, and click Authorize. The CLI then receives an ordinary API key, so everything on this page applies to it.

On a server, over SSH or in an agent sandbox without a browser, open zooop.ai/cli/login on any device and type the code. In CI, skip the login and set ZOOOP_API_KEY instead — it always takes precedence.

Logging in again from the same machine replaces that machine’s previous CLI key, so repeated logins don’t pile up. zooop logout revokes the key on the server and deletes the local copy.

Every command with examples: the ZOOOP CLI guide. The three endpoints below are what the CLI calls. They follow the OAuth 2.0 device authorization grant (RFC 8628), so you can use them to sign in your own tool the same way.

npx zooop login
# Open https://zooop.ai/cli/login?code=QBKF-7XRM and check the code: QBKF-7XRM
zooop whoami
zooop templates --type video
zooop run --template superhero-movie-poster -p 'image_urls=["@./me.jpg"]' --out ./results
zooop tasks
zooop logout
POST

Start a CLI login

https://zooop.ai/api/public/v1/cli/device

Create a login request. No authentication — the client has no key yet.

Rate limit: 10 requests/min per client IP. The approval page also shows the country the request came from, so a user can spot a code someone else forwarded to them.

Parameters

clientName
string
Your tool’s name, shown on the approval page (max 40 chars).
clientVersion
string
Tool version, shown on the approval page.
deviceName
string
Machine name, shown on the approval page and used in the key label.
platform
string
OS name, shown on the approval page.
installationId
string
A random id your tool keeps per install (8–64 letters, digits or dashes). A new login from the same install replaces its previous key.

Response

deviceCode
string
Secret your tool polls with. Keep it private.
userCode
string
Short code to show the user, `XXXX-XXXX`.
verificationUri
string
Where the user approves: `https://zooop.ai/cli/login`.
verificationUriComplete
string
Same page with the code filled in — open this one.
expiresIn
number
Seconds until the request expires (600).
interval
number
Seconds to wait between polls (5).
Example response
{
"deviceCode": "8yq0rQ1zP2c9...",
"userCode": "QBKF-7XRM",
"verificationUri": "https://zooop.ai/cli/login",
"verificationUriComplete": "https://zooop.ai/cli/login?code=QBKF-7XRM",
"expiresIn": 600,
"interval": 5
}
curl -X POST https://zooop.ai/api/public/v1/cli/device \
-H "Content-Type: application/json" \
-d '{ "clientName": "my-tool", "deviceName": "build-box", "installationId": "3f0c8a2e-1b7d-4c55-9e10-6a2f4d8b9c01" }'
POST

Poll for the key

https://zooop.ai/api/public/v1/cli/token

Poll with the device code until the user approves; the key is returned once.

Rate limit: 60 requests/min per client IP. Until the user decides, every poll returns 400 with one of these codes:

codeWhat to do
authorization_pendingKeep polling every interval seconds
slow_downYou polled too fast — add 5 seconds to the interval
access_deniedThe user denied (or can no longer issue that key) — stop
expired_token10 minutes passed — start a new login
invalid_grantUnknown code, or the key was already handed out — stop

Parameters

deviceCodeRequired
string
The `deviceCode` from Start a CLI login.

Response

apiKey
string
The new API key (`zpk_live_…`). Returned only in this response.
keyPrefix
string
Display prefix of the key.
expiresAt
string | null
ISO 8601 expiry the user picked (30, 90 or 365 days).
user
object
{ email, name } of the user who approved.
account
object
{ type: `personal` | `team`, organizationId, name } — whose credits the key spends.
project
object
{ id, name } of the project results go to.
Example response
{
"apiKey": "zpk_live_…",
"keyPrefix": "zpk_live_8fQe2kLm",
"expiresAt": "2027-01-16T08:00:00.000Z",
"user": { "email": "you@example.com", "name": "You" },
"account": { "type": "personal", "organizationId": null, "name": null },
"project": { "id": "project-uuid", "name": "API Playground" }
}
curl -X POST https://zooop.ai/api/public/v1/cli/token \
-H "Content-Type: application/json" \
-d '{ "deviceCode": "DEVICE_CODE" }'
POST

Revoke the calling key

https://zooop.ai/api/public/v1/cli/logout

Log out: permanently revoke the key that authenticates this request.

Authorization required. Rate limit: 120 requests/min per key. A key can only revoke itself; it stops working on every endpoint at once.

Response

revoked
boolean
`true` when the key was revoked by this call.
Example response
{ "revoked": true }
curl -X POST https://zooop.ai/api/public/v1/cli/logout \
-H "Authorization: Bearer $ZOOOP_API_KEY"
POST

Create a task

https://zooop.ai/api/public/v1/tasks

Submit a generation request. Returns a queued task you can poll.

Authorization required. Rate limit: 60 requests/min per key.

Idempotency — pass an Idempotency-Key header (1–256 chars). Repeats within 24 hours return the original task instead of creating a new one.

Billing — credits are charged when the task is created and refunded automatically if it fails or is cancelled. A template with a per-resolution price table charges the listed price for the resolution the task runs at (never less than the model’s own price); POST /quote returns the exact figure.

Errors: 400 invalid_payload / invalid_idempotency_key / missing_required_params / param_out_of_domain / param_conflict / foreign_url, 402 arrears / token_daily_cap_exceeded, 403 model_not_public, 404 unknown_model / unknown_ai_tool / unknown_template, 422 moderation_blocked and media checks, 429 rate_limited / token_daily_cap_reached, team-key errors (see Errors & rate limits).

Parameters

interfaceIdRequired
string
Model interface to run. Required with `versionId`. Mutually exclusive with `aiTool` / `template`.
versionIdRequired
string
Interface version to run. Required when `interfaceId` is provided.
aiTool
string
An AI-tool slug to run instead of a raw model. Mutually exclusive with `interfaceId` / `versionId` / `template`.
template
string
A template slug to run instead of a raw model — the same templates published at `/templates/{slug}`. Mutually exclusive with `interfaceId` / `versionId` / `aiTool`.
paramsRequired
object
Generation parameters for the chosen model. Up to 50 keys.
prompt
string
Text prompt. Up to 10,000 characters.
[other params]
string | number | boolean | array
Model-specific params (discover them via `GET /models`). String values up to 10,000 chars; arrays up to 20 items of at most 2,000 chars each; nested objects are not accepted. Media URLs must be hosted on zooop.ai — upload them via `POST /uploads` first (`400 foreign_url` otherwise).

Response

taskId
string
The created task id. Use it with `GET /tasks/{id}`.
status
string
`queued` for a new task. An idempotent replay returns the existing task’s current status.
modelId
string
The resolved interface id.
versionId
string
The resolved version id.
idempotent
boolean
Present and `true` only when an idempotent retry matched an existing task.
Example response
{
"taskId": "a1b2c3d4-0000-0000-0000-000000000000",
"status": "queued",
"modelId": "img-interface-id",
"versionId": "v1-version-id"
}
curl -X POST https://zooop.ai/api/public/v1/tasks \
-H "Authorization: Bearer $ZOOOP_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-unique-key-123" \
-d '{
"interfaceId": "your-model-interface-id",
"versionId": "your-model-version-id",
"params": { "prompt": "a cinematic shot of a city at night" }
}'
GET

Get a task

https://zooop.ai/api/public/v1/tasks/{id}

Fetch a task by id. Poll this until status is terminal.

Authorization required. No fixed rate limit — poll every few seconds.

Scope — the key owner’s tasks in the key’s scope: team tasks for a team key, personal tasks for a personal key, including ones made in the web app. Any other task id returns 404 unknown_task.

Parameters

idRequired
string
Path parameter — the task id returned by Create a task.

Response

taskId
string
The task id.
status
string
One of `queued`, `running`, `succeeded`, `failed`, `cancelled`. Poll until it is one of the last three (terminal).
type
string
What the task produces: `image`, `video` or `audio`.
kind
string
The specific kind of generation, e.g. `t2i`, `i2v`, `first-last-frame`, `text-to-speech`.
modelId
string | null
The interface id the task ran.
outputs
object[]
Every result asset, in order (some models return several). Empty until the task succeeds.
url
string
Full URL of the generated asset.
thumbnailUrl
string
Optional thumbnail URL.
error
object | null
Present when `status` is `failed` or `cancelled`, otherwise null.
message
string
Human-readable failure reason.
code
string
Machine-readable failure code.
creditsCharged
number
Credits charged for the task; `0` once it was refunded (failed or cancelled).
createdAt
string
ISO 8601 creation timestamp.
completedAt
string | null
ISO 8601 timestamp, set when the task reaches a terminal state.
Example response
{
"taskId": "a1b2c3d4-0000-0000-0000-000000000000",
"status": "succeeded",
"type": "image",
"kind": "t2i",
"modelId": "img-interface-id",
"outputs": [
{
"url": "https://zooop.ai/cdn/.../result.png",
"thumbnailUrl": "https://zooop.ai/cdn/.../thumb.png"
}
],
"error": null,
"creditsCharged": 12,
"createdAt": "2026-06-22T10:00:00.000Z",
"completedAt": "2026-06-22T10:00:45.000Z"
}
curl https://zooop.ai/api/public/v1/tasks/TASK_ID \
-H "Authorization: Bearer $ZOOOP_API_KEY"
GET

List tasks

https://zooop.ai/api/public/v1/tasks

Page through your tasks in the key’s project, newest first.

Authorization required. Rate limit: 120 requests/min per key.

Scope — the key owner’s tasks in the project the key is bound to: team tasks for a team key, personal tasks for a personal key. That includes tasks made in the web app in that project and by other keys bound to it.

Errors: 400 invalid_status / invalid_page / invalid_page_size.

Parameters

status
query string
Optional filter: `queued`, `running`, `succeeded`, `failed` or `cancelled`.
page
query string
Page number, from 1 (default 1, max 500).
pageSize
query string
Tasks per page, 1–100 (default 20).

Response

tasks
object[]
Tasks in the same shape as `GET /tasks/{id}`.
page
number
The page returned.
pageSize
number
The page size used.
hasMore
boolean
Whether a next page exists.
Example response
{
"tasks": [
{
"taskId": "a1b2c3d4-0000-0000-0000-000000000000",
"status": "succeeded",
"type": "video",
"kind": "i2v",
"modelId": "video-interface-id",
"outputs": [ { "url": "https://storage.zooop.ai/.../clip.mp4" } ],
"error": null,
"creditsCharged": 70,
"createdAt": "2026-10-18T09:00:00.000Z",
"completedAt": "2026-10-18T09:02:10.000Z"
}
],
"page": 1,
"pageSize": 20,
"hasMore": false
}
curl "https://zooop.ai/api/public/v1/tasks?status=succeeded&pageSize=10" \
-H "Authorization: Bearer $ZOOOP_API_KEY"
POST

Cancel a task

https://zooop.ai/api/public/v1/tasks/{id}/cancel

Cancel a task that is still queued and get its credits back.

Authorization required. Rate limit: 60 requests/min per key. Same ownership rule as GET /tasks/{id}.

Only a queued task can be cancelled. Once the provider has it (running), the generation can’t be stopped and is billed normally. Repeating the call on a cancelled task returns 200 again with refundedCredits: 0.

Credits go back to the wallet that paid: the team’s for a team task, yours otherwise.

Errors: 404 unknown_task, 409 cancel_too_late (already running), 409 task_already_finished (already succeeded or failed). Both 409s carry error.taskStatus.

Parameters

idRequired
string
Path parameter — the task id.

Response

taskId
string
The task id.
status
string
Always `cancelled`.
refundedCredits
number
Credits refunded by this call (0 when it was already cancelled).
Example response
{
"taskId": "a1b2c3d4-0000-0000-0000-000000000000",
"status": "cancelled",
"refundedCredits": 70
}
curl -X POST https://zooop.ai/api/public/v1/tasks/TASK_ID/cancel \
-H "Authorization: Bearer $ZOOOP_API_KEY"
POST

Upload a file

https://zooop.ai/api/public/v1/uploads

Upload media to get a zooop.ai URL you can pass into task params.

Authorization required. Rate limit: 30 requests/min per key.

Uploads are checked against the content policy: images right away (451 moderation_blocked with labels), videos in the background (202, then poll). When video checks are switched off, a video comes back ready directly. Audio is not checked.

Errors: 400 invalid_payload, 402 arrears, 413 file_too_large, 451 moderation_blocked, 429 rate_limited, 502 storage_upload_failed, 503 moderation_unavailable.

Parameters

Content-TypeRequired
header
The file’s MIME type. Allowed: image/png, image/jpeg (or image/jpg), image/webp, image/gif, audio/mpeg (or audio/mp3), audio/wav, audio/ogg, audio/webm, video/mp4, video/webm, video/quicktime. Anything else returns `400` with an `allowed` list.
bodyRequired
binary
The raw file bytes (NOT multipart/form-data). Max 100 MB. Set `Content-Length`.

Response

status
string
`ready` (200) when the file is usable now, or `processing` (202) while a video is still being checked — poll `GET /uploads/{uploadId}`.
url
string
CDN URL of the uploaded file. Pass this into task `params`. (ready only)
size
number
Byte size as stored (ready only). Images are resized to at most 2048 px on the longest edge, so this can be smaller than what you sent.
contentType
string
Echoed MIME type (ready only).
uploadId
string
Poll id for async video uploads (processing only).
pollUrl
string
Path to poll for async video uploads (processing only).
Example response
// image / audio — 200 OK
{
"status": "ready",
"url": "https://cdn.zooop.ai/.../file.png",
"size": 482113,
"contentType": "image/png"
}
// video — 202 Accepted (poll for moderation)
{
"status": "processing",
"uploadId": "b2c3d4e5-...",
"pollUrl": "/api/public/v1/uploads/b2c3d4e5-..."
}
# Send raw bytes; Content-Type must match the file
curl -X POST https://zooop.ai/api/public/v1/uploads \
-H "Authorization: Bearer $ZOOOP_API_KEY" \
-H "Content-Type: image/png" \
--data-binary @./input.png
GET

Get an upload

https://zooop.ai/api/public/v1/uploads/{uploadId}

Poll an async (video) upload until moderation finishes.

Authorization required. Rate limit: 120 requests/min per key. Scoped to your key (others’ uploads return 404 unknown_upload).

Parameters

uploadIdRequired
string
Path parameter — the `uploadId` from a processing upload.

Response

status
string
One of `processing` (202), `ready`, `blocked`, `errored`.
url
string
CDN URL (ready only).
contentType
string
MIME type (ready only).
labels
string
Comma-separated moderation labels (blocked only).
error
string
Human-readable reason (blocked only).
reason
string
Failure reason (errored only).
Example response
// ready — 200 OK
{
"status": "ready",
"url": "https://cdn.zooop.ai/.../clip.mp4",
"contentType": "video/mp4"
}
curl https://zooop.ai/api/public/v1/uploads/UPLOAD_ID \
-H "Authorization: Bearer $ZOOOP_API_KEY"
GET

List models

https://zooop.ai/api/public/v1/models

Discover models and their interfaceId / versionId pairs and params.

Authorization required. No fixed rate limit. Both type and subtype are required query params: a missing one returns 400 missing_category, an unknown pair 400 unknown_category; both carry a validCategories list.

Parameters

typeRequired
query string
Media category, e.g. `image`, `video`, `audio`.
subtypeRequired
query string
Sub-category. Valid pairs: image `default` (text/image to image), `edit-image`, `image-svg`; video `text-ref`, `motion-control`, `first-last-frame`, `extend-video`, `video-edit`, `audio-lipsync`, `video-sfx`; audio `text-to-speech`, `voice-clone`, `sound-effect`, `music`.

Response

models
object[]
Available models for the category.
id
string
interfaceId — pass to `POST /tasks`.
name
string
Display name.
type
string
Media category (`image`, `video`, `audio`).
subType
string
Sub-category.
description
string
Short description.
brand
object | null
{ id, name, logo } of the model maker.
promptRequired
boolean
Whether a prompt is required.
promptMaxLength
number | null
Prompt length limit for this model, if any.
tags
string[]
Badges such as `NEW` / `HOT`.
params
object[]
Param definitions: id, type, displayName, required, default, constraints, options. Voice options expand to { value, label, previewUrl }.
versions
object[]
Versions, each with id (versionId), name, description and `typicalPrice` { typicalCredits, unit, note }.
Example response
{
"models": [
{
"id": "interface-uuid",
"name": "Seedream 5.0 Lite",
"type": "image",
"subType": "default",
"promptRequired": true,
"params": [ { "id": "aspect_ratio", "type": "enum", "options": ["1:1", "16:9"] } ],
"versions": [
{ "id": "version-uuid", "name": "v1", "typicalPrice": { "typicalCredits": 4, "unit": "image" } }
]
}
]
}
curl "https://zooop.ai/api/public/v1/models?type=image&subtype=default" \
-H "Authorization: Bearer $ZOOOP_API_KEY"
GET

List AI tools

https://zooop.ai/api/public/v1/ai-tools

AI tools are ready-made presets (upscale, remove-bg, …) run by slug.

Authorization required. Rate limit: 120 requests/min per key. Errors: 400 invalid_type.

Parameters

type
query string
Optional filter — `image` or `video`. Omit for all.

Response

aiTools
object[]
Available AI tools.
slug
string
Stable slug — pass as `aiTool` to `POST /tasks` or `POST /quote`.
name
string
Display name.
mediaType
string
`image` or `video`.
subType
string
Free-form sub-category.
summary
string
One-line description.
coverUrl
string
Cover image URL.
tags
string[]
Tags.
params
object[]
Param definitions (same shape as models).
typicalPrice
object
{ typicalCredits, unit, note }. Omitted when no price can be derived.
Example response
{
"aiTools": [
{
"slug": "background-removal",
"name": "Background Removal",
"mediaType": "image",
"summary": "Remove the background from an image.",
"params": [ { "id": "image_url", "type": "image", "required": true } ],
"typicalPrice": { "typicalCredits": 2, "unit": "image" }
}
]
}
curl "https://zooop.ai/api/public/v1/ai-tools?type=image" \
-H "Authorization: Bearer $ZOOOP_API_KEY"
GET

Get an AI tool

https://zooop.ai/api/public/v1/ai-tools/{slug}

Fetch a single AI tool by slug, including its params.

Authorization required. Rate limit: 120 requests/min per key. Errors: 404 unknown_ai_tool.

Parameters

slugRequired
string
Path parameter — the tool’s slug.

Response

slug
string
Stable slug.
name
string
Display name.
mediaType
string
`image` or `video`.
subType
string
Free-form sub-category.
summary
string
One-line description.
coverUrl
string
Cover image URL.
tags
string[]
Tags.
params
object[]
Param definitions.
typicalPrice
object
{ typicalCredits, unit, note }. Omitted when no price can be derived.
Example response
{
"slug": "background-removal",
"name": "Background Removal",
"mediaType": "image",
"summary": "Remove the background from an image.",
"params": [ { "id": "image_url", "type": "image", "required": true } ],
"typicalPrice": { "typicalCredits": 2, "unit": "image" }
}
curl https://zooop.ai/api/public/v1/ai-tools/background-removal \
-H "Authorization: Bearer $ZOOOP_API_KEY"
GET

List templates

https://zooop.ai/api/public/v1/templates

Templates are the one-click presets published at /templates — a tuned prompt plus a bound model, run by slug.

Authorization required. Rate limit: 120 requests/min per key. Errors: 400 invalid_type.

Every approved, live template is listed — official and community alike. Running a community template attributes its creator exactly as the website does.

Parameters

type
query string
Optional filter — `image` or `video`. Omit for all.

Response

templates
object[]
Published templates, in gallery order.
slug
string
Stable slug — pass as `template` to `POST /tasks` or `POST /quote`.
name
string
Display name.
mediaType
string
`image` or `video`.
summary
string
One-line description.
subType
string
Free-form sub-category.
coverUrl
string
Cover image or video URL.
tags
string[]
Tags (they also drive the category pages, e.g. AI dance).
params
object[]
Only the inputs this template leaves editable — the prompt and every tuned setting are already baked in. When a param lists `options`, only those values are accepted.
official
boolean
`true` for ZOOOP-authored templates, `false` for community ones.
typicalPrice
object
{ typicalCredits, unit, note }. For a template priced per resolution: the price per run at its default resolution, with every resolution’s price in `note`. Omitted when no price can be derived.
Example response
{
"templates": [
{
"slug": "superhero-movie-poster",
"name": "Superhero Movie Poster",
"mediaType": "image",
"summary": "One photo becomes a blockbuster teaser poster.",
"coverUrl": "https://storage.zooop.ai/global/website/templates/superhero-movie-poster-cover.webp",
"params": [
{ "id": "image_urls", "type": "image_urls", "displayName": "Your photo", "constraints": { "maxCount": 1 } },
{ "id": "hero_name", "type": "text", "displayName": "Poster title", "default": "NIGHTFALL" }
],
"official": true,
"typicalPrice": { "typicalCredits": 5, "unit": "image" }
}
]
}
curl "https://zooop.ai/api/public/v1/templates?type=image" \
-H "Authorization: Bearer $ZOOOP_API_KEY"
GET

Get a template

https://zooop.ai/api/public/v1/templates/{slug}

Fetch one template by slug, including exactly which inputs it expects.

Authorization required. Rate limit: 120 requests/min per key. Errors: 404 unknown_template (unknown, unpublished or retired).

Parameters

slugRequired
string
Path parameter — the template’s slug, same one used in `/templates/{slug}` on the site.

Response

slug
string
Stable slug.
name
string
Display name.
mediaType
string
`image` or `video`.
summary
string
One-line description.
subType
string
Free-form sub-category.
coverUrl
string
Cover image or video URL.
tags
string[]
Tags.
params
object[]
The editable inputs. Submit values keyed by each `id`; when a param lists `options`, only those values are accepted.
official
boolean
ZOOOP-authored or community.
typicalPrice
object
{ typicalCredits, unit, note } — see List templates.
Example response
{
"slug": "superhero-movie-poster",
"name": "Superhero Movie Poster",
"mediaType": "image",
"summary": "One photo becomes a blockbuster teaser poster.",
"params": [
{ "id": "image_urls", "type": "image_urls", "displayName": "Your photo", "constraints": { "maxCount": 1 } },
{ "id": "hero_name", "type": "text", "displayName": "Poster title", "default": "NIGHTFALL" }
],
"official": true,
"typicalPrice": { "typicalCredits": 5, "unit": "image" }
}
curl https://zooop.ai/api/public/v1/templates/superhero-movie-poster \
-H "Authorization: Bearer $ZOOOP_API_KEY"
# then run it — only the inputs it left editable
curl -X POST https://zooop.ai/api/public/v1/tasks \
-H "Authorization: Bearer $ZOOOP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template":"superhero-movie-poster","params":{"image_urls":["https://storage.zooop.ai/…"],"hero_name":"DAFU"}}'
POST

Quote a task

https://zooop.ai/api/public/v1/quote

Estimate the credit cost of a task before submitting. Never charges.

Authorization required. Rate limit: 120 requests/min per key. The quote equals what POST /tasks charges for the same body, as long as the input media don’t change. Errors: 400 invalid_payload / missing_required_params / param_out_of_domain, 403 model_not_public, 404 unknown_model / unknown_ai_tool / unknown_template, 422 media checks, 503 pricing_misconfigured.

Parameters

interfaceId
string
With `versionId` — the model to price. Mutually exclusive with `aiTool` / `template`.
versionId
string
Required with `interfaceId`.
aiTool
string
An AI-tool slug. Mutually exclusive with `interfaceId` / `template`.
template
string
A template slug. Mutually exclusive with `interfaceId` / `aiTool`.
params
object
Same params as `POST /tasks`.

Response

credits
number
Estimated credit cost.
estimatedSeconds
number | null
Best-effort ETA; null for new models with no history.
modelId
string
Resolved interface id.
versionId
string
Resolved version id.
modelName
string
Resolved model name.
breakdown
object
How `credits` was computed.
pricingKey
string
The price-table entry used (e.g. `720p`).
base
number
Per-unit price of that entry.
multiplier
number
Units billed (seconds, characters, …; 1 for flat prices).
tierBasePrice
number
Flat add-on of that entry.
surcharges
object[]
Per-item extras, e.g. reference images.
basePrice
number
Flat price added to every request.
minPriceApplied
boolean
Whether the model’s minimum price kicked in.
templatePrice
object
Templates priced per resolution only: { modelCost, configured, tierPrices } — the model’s own price for this request, the listed price applied (null when the table has no entry for it) and the whole table.
Example response
{
"credits": 180,
"estimatedSeconds": 95,
"modelId": "interface-uuid",
"versionId": "version-uuid",
"modelName": "Wan V3.0",
"breakdown": {
"pricingKey": "480p",
"base": 7,
"multiplier": 11,
"tierBasePrice": 0,
"surcharges": [],
"basePrice": 0,
"minPriceApplied": false,
"templatePrice": { "modelCost": 77, "configured": 180, "tierPrices": { "480p": 180, "720p": 257 } }
}
}
curl -X POST https://zooop.ai/api/public/v1/quote \
-H "Authorization: Bearer $ZOOOP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "interfaceId": "...", "versionId": "...", "params": { "prompt": "..." } }'
POST

Describe an image

https://zooop.ai/api/public/v1/describe-image

Analyze a reference image into a ready-to-use prompt. Costs 1 credit.

Authorization required. Rate limit: 10 requests/min per key (vision is expensive). Charges 1 credit up front, refunded on failure.

Errors: 400 invalid_payload, 402 insufficient_credits / arrears, 422 policy_violation, 429 token_daily_cap_reached / rate_limited / upstream_rate_limited, 500 describe_failed, 503 vision_unavailable, plus the team-key errors.

Parameters

imageUrlRequired
string
A zooop.ai CDN image URL (from `POST /uploads`). External URLs are rejected.
language
string
Optional output language: one of `en`, `zh`, `zh-TW`, `ja`, `fr`, `es`, `pt`, `ru`, `de`, `it`, `ar`, `tr`, `nl`, `da`, `nb`, `pl`, `th`, `id`, `hi`, `bn`, `vi`. Anything else falls back to English.

Response

overallDescription
string
The canonical, ready-to-use description (always non-empty).
subject
string
Best-effort dimension fields: subject, composition, style, lighting, palette, mood.
camera
string | null
Camera notes, may be null.
credits
number
Always 1.
Example response
{
"credits": 1,
"overallDescription": "A neon-lit alley at night, rain-slicked...",
"subject": "a lone figure under an umbrella",
"composition": "centered, low angle",
"style": "cinematic, cyberpunk",
"lighting": "neon, high contrast",
"palette": "magenta and teal",
"mood": "moody",
"camera": "35mm, shallow depth of field"
}
curl -X POST https://zooop.ai/api/public/v1/describe-image \
-H "Authorization: Bearer $ZOOOP_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "imageUrl": "https://cdn.zooop.ai/.../ref.png", "language": "en" }'
GET

Inspect your key

https://zooop.ai/api/public/v1/me

Introspect the calling key: quota, limits, project, and balance.

Authorization required. Rate limit: 120 requests/min per key. Team keys return team instead of user (the creator’s personal balance is never exposed).

Response

key
object
The calling key.
id
string
Key id.
prefix
string
Display prefix, e.g. `zpk_live_AbCdEfGh`.
label
string
Your label for the key.
createdAt
string
ISO 8601 creation time.
expiresAt
string | null
ISO 8601 expiry, or null.
dailyCreditCap
number | null
Daily credit cap, or null for unlimited.
creditsSpentToday
number
Credits this key spent today.
creditsRemainingToday
number | null
cap − spent, or null if no cap.
project
object
The bound project { id, name }.
user
object
{ creditBalance } — personal keys only.
team
object
{ id, creditBalance } — team keys only.
limits
object
Current per-minute rate limits: tasksPerMin, uploadsPerMin, uploadPollPerMin, quotePerMin, aiToolsPerMin, templatesPerMin, describeImagePerMin, taskListPerMin, taskCancelPerMin.
Example response
{
"key": {
"id": "token-uuid",
"prefix": "zpk_live_AbCdEfGh",
"label": "Production",
"createdAt": "2026-10-01T08:00:00.000Z",
"expiresAt": null,
"dailyCreditCap": 1000,
"creditsSpentToday": 120,
"creditsRemainingToday": 880
},
"project": { "id": "project-uuid", "name": "My Project" },
"user": { "creditBalance": 5000 },
"limits": { "tasksPerMin": 60, "uploadsPerMin": 30, "uploadPollPerMin": 120, "quotePerMin": 120, "aiToolsPerMin": 120, "templatesPerMin": 120, "describeImagePerMin": 10, "taskListPerMin": 120, "taskCancelPerMin": 60 }
}
curl https://zooop.ai/api/public/v1/me \
-H "Authorization: Bearer $ZOOOP_API_KEY"