# EggAPI > EggAPI is an AI model aggregation API. One API key and one REST endpoint, `POST https://api.eggapi.ai/v1/generate`, run image models (Seedream, Nano Banana, GPT Image 2) and video models (Seedance, Wan). Every task is asynchronous: create it, then poll `GET https://api.eggapi.ai/v1/tasks/{id}` or receive a webhook. AI agents can connect over MCP at `https://api.eggapi.ai/mcp`. - Base URL: `https://api.eggapi.ai` - Auth: `Authorization: Bearer `, keys are created at https://eggapi.ai/dashboard - Responses use the envelope `{ "data": ..., "error": null }` or `{ "data": null, "error": { "code", "message" } }` - Video requests need `duration` in seconds; edit and image-to-video models need `image_urls` # EggAPI Documentation > One API key for image and video generation models from ByteDance, Google, OpenAI, and Alibaba Source: https://eggapi.ai/docs EggAPI is an AI model gateway for production generation workloads. One API key and one REST endpoint give you image models (Seedream, Nano Banana, GPT Image 2) and video models (Seedance, Wan). EggAPI authenticates the request, creates an asynchronous task, routes it to an upstream provider with automatic fallback, stores the output files, bills your balance, and can notify your webhook when the task finishes. - [Quickstart](https://eggapi.ai/docs/quickstart): Create an API key, submit a task, and poll the result. - [Models](https://eggapi.ai/docs/models): Every published model ID, its generation type, and how it is billed. - [Connect AI Agents (MCP)](https://eggapi.ai/docs/mcp): Let Claude Code, Codex, or Cursor generate images and videos with your key. - [API Reference](https://eggapi.ai/docs/api-reference): Base URL, response envelope, status codes, pagination, and every endpoint. ## How EggAPI Works 1. **Submit.** Call `POST /v1/generate` with `Authorization: Bearer YOUR_API_KEY`, a model ID such as `google/nano-banana-2/text-to-image`, and a `prompt`. 2. **Route.** The Go backend validates your key, creates a task, and sends it through the model's provider route chain, falling back to the next provider when one fails. 3. **Process.** Workers poll the upstream provider, store generated files on `file.eggapi.ai`, and persist the task output. 4. **Settle.** EggAPI deducts your balance, writes a usage record, and sends a signed webhook if you supplied `webhook_url`. ## First Request ```bash curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "google/nano-banana-2/text-to-image", "prompt": "A clean product render of a ceramic espresso cup on a walnut desk", "aspect_ratio": "16:9", "resolution": "1k" }' ``` `POST /v1/generate` returns `202 Accepted` with a task in status `pending`. Poll `GET /v1/tasks/{id}` until the status becomes `completed` or `failed`, or pass `webhook_url` to be called back. ## For AI Assistants These docs are available as plain text for LLMs: - [`https://eggapi.ai/llms.txt`](https://eggapi.ai/llms.txt): index of the docs and the live model catalog with current prices. - [`https://eggapi.ai/llms-full.txt`](https://eggapi.ai/llms-full.txt): every docs page plus the full parameters of every published model, in one file. # Quickstart > Submit your first EggAPI image or video task and read the result Source: https://eggapi.ai/docs/quickstart This guide uses the production API base URL: ```text https://api.eggapi.ai ``` ## 1. Get an API Key Sign in at [eggapi.ai](https://eggapi.ai/), open the dashboard, top up your balance, and create an API key. Send the key in the `Authorization` header of every request: ```text Authorization: Bearer YOUR_API_KEY ``` ## 2. Submit a Task Every generation model is asynchronous. `POST /v1/generate` returns `202 Accepted` and a task object; the output arrives later. ```bash cURL curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "google/nano-banana-2/text-to-image", "prompt": "A cinematic product photo of a matte green travel mug", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 }' ``` ```python Python import requests response = requests.post( "https://api.eggapi.ai/v1/generate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "model": "google/nano-banana-2/text-to-image", "prompt": "A cinematic product photo of a matte green travel mug", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1, }, ) response.raise_for_status() task = response.json()["data"] print(task["id"]) ``` ```javascript JavaScript const response = await fetch("https://api.eggapi.ai/v1/generate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ model: "google/nano-banana-2/text-to-image", prompt: "A cinematic product photo of a matte green travel mug", aspect_ratio: "16:9", resolution: "1k", num_outputs: 1 }) }); if (!response.ok) throw new Error(await response.text()); const { data: task } = await response.json(); console.log(task.id); ``` Example response: ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "pending", "model": "google/nano-banana-2/text-to-image", "type": "image_generate", "cost": "$0.00", "created_at": "2026-10-26T10:30:00Z" }, "error": null } ``` ## 3. Poll the Task Use the task ID from the response: ```bash curl https://api.eggapi.ai/v1/tasks/gen_3f2a9c1d-7b4 \ -H "Authorization: Bearer YOUR_API_KEY" ``` Completed task response: ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "completed", "model": "google/nano-banana-2/text-to-image", "type": "image_generate", "output": { "url": "https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png", "urls": ["https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png"] }, "cost": "$0.0135", "created_at": "2026-10-26T10:30:00Z", "started_at": "2026-10-26T10:30:01Z", "completed_at": "2026-10-26T10:30:12Z" }, "error": null } ``` Images usually finish in seconds; videos usually take one to three minutes. Instead of polling you can pass `webhook_url` when you create the task. See [Async Tasks](https://eggapi.ai/docs/async-tasks). ## 4. Generate a Video Video models need a `duration` in seconds, because video is billed per second: ```bash curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "bytedance/seedance-2.5/text-to-video", "prompt": "A black egg cracking open under soft studio light, slow push-in", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9" }' ``` To animate your own image, upload it with [`POST /v1/uploads`](https://eggapi.ai/docs/uploads) and pass the returned URL in `image_urls` to an `image-to-video` model. See [Video Models](https://eggapi.ai/docs/models/video). ## 5. Check Usage Usage endpoints require an API key: ```bash curl https://api.eggapi.ai/v1/usage/summary \ -H "Authorization: Bearer YOUR_API_KEY" ``` Example response: ```json { "data": [ { "model": "google/nano-banana-2/text-to-image", "total_units": 1, "total_cost": "$0.0135", "request_count": 1 } ], "error": null } ``` ## Next Steps - [Models](https://eggapi.ai/docs/models): Pick a model ID and see the parameters it accepts. - [Async Tasks](https://eggapi.ai/docs/async-tasks): Poll tasks, consume webhooks, and handle failures. - [Uploads](https://eggapi.ai/docs/uploads): Host input images, videos, and audio for editing and video models. - [MCP](https://eggapi.ai/docs/mcp): Connect Claude Code, Codex, or Cursor to EggAPI. # Authentication > Authenticate EggAPI requests with API keys Source: https://eggapi.ai/docs/authentication EggAPI has two authentication modes: - Server-to-server API calls and MCP clients use API keys. - The website dashboard, playground, and admin tools use browser session cookies. This documentation covers the API key flow. ## API Key Header Send your key as a Bearer token on every request: ```text Authorization: Bearer YOUR_API_KEY ``` Example: ```bash curl https://api.eggapi.ai/v1/usage/summary \ -H "Authorization: Bearer YOUR_API_KEY" ``` The backend rejects the request when the header is missing, the format is not `Bearer `, the key is unknown, inactive, or expired, or the owning account is suspended. ## Creating Keys Create, rename, disable, and delete API keys from the [EggAPI dashboard](https://eggapi.ai/dashboard). Key management is a dashboard session action and is not available with an API key. The full key is shown when it is created. Store it immediately, treat it like a password, and only use it from server-side code. ## Endpoints That Accept API Keys | Endpoint | API key | Dashboard session | | --- | --- | --- | | `POST /v1/generate` | Yes | Yes (playground) | | `POST /v1/uploads` | Yes | Yes | | `GET /v1/tasks/{id}`, `GET /v1/tasks` | Yes | Yes | | `GET /v1/usage`, `GET /v1/usage/summary` | Yes | No | | `POST /mcp` ([MCP server](https://eggapi.ai/docs/mcp)) | Yes | No | | API keys, balance, webhook secret | No | Yes | API key requests are rate limited per key. When the limit is exceeded the API returns `429 RATE_LIMITED`; back off and retry. ## Security Practices - Keep API keys on your server. Do not expose them in frontend JavaScript, mobile apps, public repositories, or logs. - Use separate keys for production, staging, local development, and AI agents, so you can disable one without touching the others. - Rotate a key if it may have been exposed. - When browser users need to trigger generation, call EggAPI from a backend endpoint you control. ## Common Authentication Errors ```json { "data": null, "error": { "code": "UNAUTHORIZED", "message": "Missing Authorization header" } } ``` ```json { "data": null, "error": { "code": "UNAUTHORIZED", "message": "Invalid Authorization format, expected 'Bearer '" } } ``` ```json { "data": null, "error": { "code": "UNAUTHORIZED", "message": "API key has expired" } } ``` ```json { "data": null, "error": { "code": "FORBIDDEN", "message": "User account is suspended" } } ``` # Models > Every published EggAPI model ID, its generation type, and how it is billed Source: https://eggapi.ai/docs/models Pass one of these IDs as `model` in `POST /v1/generate`. The `/edit`, `/text-to-video`, and `/image-to-video` suffixes are part of the ID: each variant is its own model. ## Image Models | Model | API `model` value | Generation type | Resolutions | | --- | --- | --- | --- | | Seedream 5.0 Pro | `bytedance/seedream-v5.0-pro` | text-to-image | `1k`, `2k` | | Seedream 5.0 Pro Edit | `bytedance/seedream-v5.0-pro/edit` | image-to-image | `1k`, `2k` | | Seedream 4.5 | `bytedance/seedream-v4.5` | text-to-image | `1k`, `2k`, `4k` | | Seedream 4.5 Edit | `bytedance/seedream-v4.5/edit` | image-to-image | `1k`, `2k`, `4k` | | Nano Banana Pro | `google/nano-banana-pro/text-to-image` | text-to-image | `1k`, `2k`, `4k` | | Nano Banana Pro Edit | `google/nano-banana-pro/edit` | image-to-image | `1k`, `2k`, `4k` | | Nano Banana 2 | `google/nano-banana-2/text-to-image` | text-to-image | `0.5k`, `1k`, `2k`, `4k` | | Nano Banana 2 Edit | `google/nano-banana-2/edit` | image-to-image | `0.5k`, `1k`, `2k`, `4k` | | GPT Image 2 | `openai/gpt-image-2/text-to-image` | text-to-image | `1k`, `2k`, `4k` | | GPT Image 2 Edit | `openai/gpt-image-2/edit` | image-to-image | `1k`, `2k`, `4k` | See [Image Models](https://eggapi.ai/docs/models/image) for parameters and examples. ## Video Models | Model | API `model` value | Generation type | Resolutions | | --- | --- | --- | --- | | Seedance 2.5 | `bytedance/seedance-2.5/text-to-video` | text-to-video | `480p`, `720p`, `1080p` | | Seedance 2.5 | `bytedance/seedance-2.5/image-to-video` | image-to-video | `480p`, `720p`, `1080p` | | Seedance 2.0 | `bytedance/seedance-2.0/text-to-video` | text-to-video | `480p`, `720p`, `1080p`, `4k` | | Seedance 2.0 | `bytedance/seedance-2.0/image-to-video` | image-to-video | `480p`, `720p`, `1080p`, `4k` | | Wan 3.0 | `alibaba/wan-3.0/text-to-video` | text-to-video | `480p`, `720p`, `1080p` | | Wan 3.0 | `alibaba/wan-3.0/image-to-video` | image-to-video | `480p`, `720p`, `1080p` | | Wan 2.7 | `alibaba/wan-2.7/text-to-video` | text-to-video | `720p`, `1080p` | | Wan 2.7 | `alibaba/wan-2.7/image-to-video` | image-to-video | `720p`, `1080p` | See [Video Models](https://eggapi.ai/docs/models/video) for parameters and examples. > The catalog is published from the EggAPI admin and can change. The live list, with current prices, is always at [eggapi.ai/models](https://eggapi.ai/models), in [`https://eggapi.ai/llms.txt`](https://eggapi.ai/llms.txt), and from the `list_models` tool of the [MCP server](https://eggapi.ai/docs/mcp). ## Billing | Kind | Unit | Charge | | --- | --- | --- | | Image | Output image | Price for the requested `resolution` × number of returned images. | | Video | Second of video | Price for the requested `resolution` × the duration the model reports, or the requested `duration` when it reports none. | - Most models are priced per resolution. When `resolution` is omitted, the model's base price applies; a resolution the model has no price for is rejected with `400 VALIDATION_ERROR`. - Prices are shown on [eggapi.ai/pricing](https://eggapi.ai/pricing) and on each model page. - Creating a task holds its estimated cost from your balance; a request your balance cannot cover is rejected with `403 INSUFFICIENT_BALANCE`. When the task completes, the hold is settled against the actual charge, and a failed task's hold is refunded in full. Requests rejected before a task is created are not charged. ## Common Parameters These top-level fields work with every model. Model-specific options go in `parameters`. | Field | Type | Description | | --- | --- | --- | | `model` | `string` | Required. A model ID from the tables above. | | `prompt` | `string` | Required. Prompt text. 1 to 100000 characters. | | `negative_prompt` | `string` | What the output should avoid, for models that support it. Up to 1000 characters. | | `aspect_ratio` | `string` | Default `16:9`. `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, or `21:9`. | | `resolution` | `string` | Output resolution from the model's list above. Also selects the price tier. | | `num_outputs` | `integer` | Default `1`. Number of images for text-to-image models. Up to 16; each returned image is billed. | | `duration` | `integer` | Video length in seconds. Required for video models; the published video models accept 4 to 15. | | `image_urls` | `string[]` | Public `http(s)` URLs of input images: the source images of an edit model, or the first frame of an image-to-video model. Up to 32 URLs. Use [`POST /v1/uploads`](https://eggapi.ai/docs/uploads) to host local files. | | `parameters` | `object` | Model-specific options forwarded to the provider, such as `output_format`, `last_image`, `reference_images`, or `generate_audio`. Unknown top-level fields are forwarded the same way. | | `webhook_url` | `string` | Callback URL, up to 2048 characters. EggAPI sends `task.completed` or `task.failed` when the task finishes. See [Async Tasks](https://eggapi.ai/docs/async-tasks#webhooks). | | `nsfw_filter` | `boolean` | Default `false`. Screens the prompt and every input image with the NSFW filter before the model runs. A blocked request returns `400 CONTENT_BLOCKED` and is not charged; if the filter cannot give a verdict the request returns `503 MODERATION_UNAVAILABLE` and nothing is generated. Off by default for API and MCP calls, always on in the EggAPI playground. Video and audio inputs are not screened. | ## Routing and Providers Each model has a chain of upstream provider routes. EggAPI sends the task to the first healthy route and falls back to the next one when a provider fails, with a circuit breaker per route. The upstream provider is an implementation detail, not part of the API contract: the model ID, parameters, and output format stay the same whichever provider runs the task. # Image Models > Text-to-image and image editing with Seedream, Nano Banana, and GPT Image 2 Source: https://eggapi.ai/docs/models/image Image models create `image_generate` tasks (text-to-image) or `image_edit` tasks (image-to-image). Both run asynchronously through `POST /v1/generate` and are billed per output image at the price of the requested `resolution`. | Model | Text-to-image ID | Edit ID | Resolutions | Edit input images | | --- | --- | --- | --- | --- | | Seedream 5.0 Pro | `bytedance/seedream-v5.0-pro` | `bytedance/seedream-v5.0-pro/edit` | `1k`, `2k` | 1 to 8 | | Seedream 4.5 | `bytedance/seedream-v4.5` | `bytedance/seedream-v4.5/edit` | `1k`, `2k`, `4k` | 1 to 8 | | Nano Banana Pro | `google/nano-banana-pro/text-to-image` | `google/nano-banana-pro/edit` | `1k`, `2k`, `4k` | 1 to 8 | | Nano Banana 2 | `google/nano-banana-2/text-to-image` | `google/nano-banana-2/edit` | `0.5k`, `1k`, `2k`, `4k` | 1 to 8 | | GPT Image 2 | `openai/gpt-image-2/text-to-image` | `openai/gpt-image-2/edit` | `1k`, `2k`, `4k` | 1 | Every image model accepts the aspect ratios `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, and `21:9`. ## Parameters | Field | Type | Description | | --- | --- | --- | | `model` | `string` | Required. A text-to-image or edit ID from the table. | | `prompt` | `string` | Required. What to create, or the edit to apply to the input images. | | `image_urls` | `string[]` | Required for edit models: public `http(s)` URLs of the source images, within the model's input limit. Not used by text-to-image models. | | `aspect_ratio` | `string` | Default `16:9`. `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, or `21:9`. | | `resolution` | `string` | One of the model's resolutions. Higher resolutions can cost more. | | `num_outputs` | `integer` | Default `1`. Number of images for text-to-image models. Each returned image is billed. | | `parameters.output_format` | `string` | `png`, `jpeg`, or `webp`, where the model supports it. | ## Generate an Image ```bash cURL curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "bytedance/seedream-v4.5", "prompt": "A clean editorial photo of a lemon tart on a steel table", "aspect_ratio": "4:3", "resolution": "2k", "num_outputs": 1, "parameters": { "output_format": "png" } }' ``` ```python Python import requests response = requests.post( "https://api.eggapi.ai/v1/generate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "model": "bytedance/seedream-v4.5", "prompt": "A clean editorial photo of a lemon tart on a steel table", "aspect_ratio": "4:3", "resolution": "2k", "num_outputs": 1, "parameters": {"output_format": "png"}, }, ) task = response.json()["data"] print(task["id"]) ``` ```javascript JavaScript const response = await fetch("https://api.eggapi.ai/v1/generate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ model: "bytedance/seedream-v4.5", prompt: "A clean editorial photo of a lemon tart on a steel table", aspect_ratio: "4:3", resolution: "2k", num_outputs: 1, parameters: { output_format: "png" } }) }); const { data: task } = await response.json(); console.log(task.id); ``` Response: ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "pending", "model": "bytedance/seedream-v4.5", "type": "image_generate", "cost": "$0.00", "created_at": "2026-10-26T10:30:00Z" }, "error": null } ``` ## Edit an Image Use an edit model and pass the source images in `image_urls`. To edit a local file, upload it first with [`POST /v1/uploads`](https://eggapi.ai/docs/uploads). ```bash curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "google/nano-banana-pro/edit", "prompt": "Replace the background with a quiet marble kitchen", "image_urls": ["https://file.eggapi.ai/uploads/image/your-user-id/input.png"], "resolution": "2k" }' ``` The task type is `image_edit`. A request to an edit model without input images is rejected with `400 VALIDATION_ERROR`. ## Completed Output ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "completed", "model": "bytedance/seedream-v4.5", "type": "image_generate", "output": { "url": "https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png", "urls": ["https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png"] }, "cost": "$0.0500", "created_at": "2026-10-26T10:30:00Z", "started_at": "2026-10-26T10:30:01Z", "completed_at": "2026-10-26T10:30:10Z" }, "error": null } ``` `output.urls` lists every image; `output.url` is the first one. # Video Models > Text-to-video and image-to-video with Seedance and Wan Source: https://eggapi.ai/docs/models/video Video models create `video_generate` tasks through `POST /v1/generate`. They are billed per second of video at the price of the requested `resolution`, so every video request needs a `duration`. | Model | Text-to-video ID | Image-to-video ID | Resolutions | | --- | --- | --- | --- | | Seedance 2.5 | `bytedance/seedance-2.5/text-to-video` | `bytedance/seedance-2.5/image-to-video` | `480p`, `720p`, `1080p` | | Seedance 2.0 | `bytedance/seedance-2.0/text-to-video` | `bytedance/seedance-2.0/image-to-video` | `480p`, `720p`, `1080p`, `4k` | | Wan 3.0 | `alibaba/wan-3.0/text-to-video` | `alibaba/wan-3.0/image-to-video` | `480p`, `720p`, `1080p` | | Wan 2.7 | `alibaba/wan-2.7/text-to-video` | `alibaba/wan-2.7/image-to-video` | `720p`, `1080p` | Every video model accepts durations from 4 to 15 seconds and the aspect ratios `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, and `21:9`. Rendering usually takes one to three minutes. ## Parameters | Field | Type | Description | | --- | --- | --- | | `model` | `string` | Required. A text-to-video or image-to-video ID from the table. | | `prompt` | `string` | Required. The scene, or the motion to apply to the first frame. | | `duration` | `integer` | Required. Length in seconds, 4 to 15. The task is billed for the duration the model reports, or this value when it reports none. A video request without `duration` is rejected with `400 VALIDATION_ERROR`. | | `resolution` | `string` | One of the model's resolutions. Selects the per-second price. | | `aspect_ratio` | `string` | Default `16:9`. `16:9`, `9:16`, `4:3`, `3:4`, `1:1`, or `21:9`. | | `image_urls` | `string[]` | Image-to-video only: the first frame, as one public `http(s)` URL. Required for image-to-video models. | | `parameters.last_image` | `string` | Image-to-video only: URL of the last frame, to animate from the first frame to this one. | | `parameters.reference_images` | `string[]` | Text-to-video only: URLs of reference images for subjects, style, or scenes. | | `parameters.reference_videos` | `string[]` | Text-to-video only: URLs of reference videos. | | `parameters.reference_audios` | `string[]` | Text-to-video only: URLs of reference audio clips. | | `parameters.generate_audio` | `boolean` | Generate a soundtrack with the video, where the model supports it. | | `parameters.enable_web_search` | `boolean` | Let the model search the web for context about the prompt, where the model supports it. | Upload local frames or reference media with [`POST /v1/uploads`](https://eggapi.ai/docs/uploads) and pass the returned URLs. ## Text to Video ```bash cURL curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "bytedance/seedance-2.5/text-to-video", "prompt": "A black egg cracking open under soft studio light, slow push-in", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9", "parameters": { "generate_audio": true } }' ``` ```python Python import requests response = requests.post( "https://api.eggapi.ai/v1/generate", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "model": "bytedance/seedance-2.5/text-to-video", "prompt": "A black egg cracking open under soft studio light, slow push-in", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9", "parameters": {"generate_audio": True}, }, ) task = response.json()["data"] print(task["id"]) ``` ```javascript JavaScript const response = await fetch("https://api.eggapi.ai/v1/generate", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ model: "bytedance/seedance-2.5/text-to-video", prompt: "A black egg cracking open under soft studio light, slow push-in", duration: 5, resolution: "720p", aspect_ratio: "16:9", parameters: { generate_audio: true } }) }); const { data: task } = await response.json(); console.log(task.id); ``` ## Image to Video Pass the first frame in `image_urls`, and optionally the last frame in `parameters.last_image`: ```bash curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "alibaba/wan-3.0/image-to-video", "prompt": "The camera slowly orbits the product while light sweeps across it", "image_urls": ["https://file.eggapi.ai/uploads/image/your-user-id/first.png"], "duration": 5, "resolution": "1080p", "parameters": { "last_image": "https://file.eggapi.ai/uploads/image/your-user-id/last.png" } }' ``` An image-to-video request without a first frame is rejected with `400 VALIDATION_ERROR`. ## Completed Output ```json { "data": { "id": "gen_8c41e07a-2d9", "status": "completed", "model": "bytedance/seedance-2.5/text-to-video", "type": "video_generate", "output": { "url": "https://file.eggapi.ai/videos/gen_8c41e07a-2d9/output.mp4", "urls": ["https://file.eggapi.ai/videos/gen_8c41e07a-2d9/output.mp4"], "duration_seconds": 5 }, "cost": "$1.2523", "created_at": "2026-10-26T10:30:00Z", "started_at": "2026-10-26T10:30:01Z", "completed_at": "2026-10-26T10:32:05Z" }, "error": null } ``` `output.duration_seconds` is the billed length when the model reports it. # Uploads > Host input images, videos, and audio on EggAPI storage for edit and video models Source: https://eggapi.ai/docs/uploads Models read input media from public `http(s)` URLs. If your files are local or private, upload them with `POST /v1/uploads` and pass the returned URLs in `image_urls` or `parameters`. ## Upload Files Send a `multipart/form-data` request with one or more files in the `files[]` field (`files` also works): ```bash curl -X POST https://api.eggapi.ai/v1/uploads \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "files[]=@./first-frame.png" \ -F "files[]=@./last-frame.png" ``` Response (`201 Created`): ```json { "data": { "files": [ { "url": "https://file.eggapi.ai/uploads/image/your-user-id/6f1c2b0e-0f1a-4f7e-9a51-3c1d2e4b5a6f.png", "key": "uploads/image/your-user-id/6f1c2b0e-0f1a-4f7e-9a51-3c1d2e4b5a6f.png", "content_type": "image/png", "size": 482113 }, { "url": "https://file.eggapi.ai/uploads/image/your-user-id/1a7d9e44-5b2c-4c8e-8f0d-9e6b7a1c2d3e.png", "key": "uploads/image/your-user-id/1a7d9e44-5b2c-4c8e-8f0d-9e6b7a1c2d3e.png", "content_type": "image/png", "size": 455870 } ] }, "error": null } ``` Then use the URLs in a generation request: ```json { "model": "bytedance/seedance-2.0/image-to-video", "prompt": "The petals unfold as the camera pulls back", "image_urls": ["https://file.eggapi.ai/uploads/image/your-user-id/6f1c2b0e-0f1a-4f7e-9a51-3c1d2e4b5a6f.png"], "duration": 5, "parameters": { "last_image": "https://file.eggapi.ai/uploads/image/your-user-id/1a7d9e44-5b2c-4c8e-8f0d-9e6b7a1c2d3e.png" } } ``` ## Limits | File type | Maximum size | | --- | --- | | Images (`image/*`) | 20 MB per file | | Videos (`video/*`) | 200 MB per file | | Audio (`audio/*`) | 50 MB per file | - One request can carry up to 512 MB in total. - Other content types are rejected with `400 VALIDATION_ERROR`. When a file has no usable `Content-Type`, EggAPI detects it from the file contents. - Uploaded files are publicly readable by URL. Do not upload anything you would not share with the model provider. ## Errors | Status | Code | Cause | | --- | --- | --- | | `400` | `VALIDATION_ERROR` | Missing `files[]`, unsupported content type, or a file over its size limit. | | `401` | `UNAUTHORIZED` | Missing or invalid API key. | | `503` | `SERVICE_UNAVAILABLE` | File storage is temporarily unavailable. | # Async Tasks > Create, poll, list, and receive callbacks for EggAPI generation tasks Source: https://eggapi.ai/docs/async-tasks Every EggAPI generation model is asynchronous. `POST /v1/generate` creates the task immediately and returns `202 Accepted`; workers process it in the background, and you read the result by polling or through a webhook. ## Lifecycle 1. Your app calls `POST /v1/generate`; the API returns `202 Accepted` with the task ID. 2. A worker starts the generation with the upstream provider and polls it until it finishes. 3. The worker saves the output, usage, and cost on the task. 4. Your app reads the task with `GET /v1/tasks/{id}` and gets it back as `completed` or `failed`. Task statuses: | Status | Meaning | | --- | --- | | `pending` | Task was created and queued. | | `processing` | Worker started provider execution or polling. | | `completed` | Output, cost, and usage have been recorded. | | `failed` | The task ended with an error message. | ## Create a Task ```bash curl -X POST https://api.eggapi.ai/v1/generate \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-image-2/text-to-image", "prompt": "A dashboard hero image with glass UI panels", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 }' ``` Response: ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "pending", "model": "openai/gpt-image-2/text-to-image", "type": "image_generate", "cost": "$0.00", "created_at": "2026-05-08T10:30:00Z" }, "error": null } ``` ## Poll a Task ```bash curl https://api.eggapi.ai/v1/tasks/gen_3f2a9c1d-7b4 \ -H "Authorization: Bearer YOUR_API_KEY" ``` Completed image task: ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "completed", "model": "openai/gpt-image-2/text-to-image", "type": "image_generate", "output": { "url": "https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png", "urls": ["https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png"] }, "cost": "$0.0096", "created_at": "2026-05-08T10:30:00Z", "started_at": "2026-05-08T10:30:01Z", "completed_at": "2026-05-08T10:30:10Z" }, "error": null } ``` ## List Tasks ```bash curl "https://api.eggapi.ai/v1/tasks?page=1&per_page=20" \ -H "Authorization: Bearer YOUR_API_KEY" ``` The list is under `data.items`, newest first, and pagination fields are under `data.pagination` (`page`, `per_page`, `total`, `total_pages`). `per_page` defaults to 20 and is at most 100. ## Webhooks Pass `webhook_url` when creating a task: ```json { "model": "google/nano-banana-2/text-to-image", "prompt": "A studio portrait with soft lighting", "webhook_url": "https://example.com/eggapi/webhook" } ``` EggAPI posts JSON to your URL after completion or failure. All models use the same webhook envelope; different result types only change `type` and the optional fields under `output`. It sends these headers: | Header | Description | | --- | --- | | `X-EggAPI-Timestamp` | Unix timestamp used in the signature payload. | | `X-EggAPI-Signature` | `sha256=` plus HMAC-SHA256 of `{timestamp}.{raw_body}` using your webhook secret. | Common fields: | Field | Description | | --- | --- | | `event` | `task.completed` or `task.failed`. | | `task_id` | EggAPI task ID, matching `data.id` from the polling API. | | `status` | `completed` or `failed`. | | `model` | Model ID from the original request. | | `type` | Task type: `image_generate`, `image_edit`, or `video_generate`. | | `output` | Present on success. Depending on the task type, it may include `url`, `urls`, `duration_seconds`, `width`, and `height`. | | `error` | Present on failure. | | `cost` | Task cost in USD as a decimal string. | | `timestamp` | Unix timestamp when the webhook payload was generated. | Completed image payload: ```json { "event": "task.completed", "task_id": "gen_3f2a9c1d-7b4", "status": "completed", "model": "google/nano-banana-2/text-to-image", "type": "image_generate", "output": { "url": "https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png", "urls": ["https://file.eggapi.ai/images/gen_3f2a9c1d-7b4/0.png"], "width": 1024, "height": 576 }, "cost": "0.013500", "timestamp": 1778217000 } ``` Completed video payload: ```json { "event": "task.completed", "task_id": "gen_8c41e07a-2d9", "status": "completed", "model": "bytedance/seedance-2.5/text-to-video", "type": "video_generate", "output": { "url": "https://file.eggapi.ai/videos/gen_8c41e07a-2d9/output.mp4", "urls": ["https://file.eggapi.ai/videos/gen_8c41e07a-2d9/output.mp4"], "duration_seconds": 5 }, "cost": "1.252275", "timestamp": 1778217000 } ``` Failed payload: ```json { "event": "task.failed", "task_id": "gen_3f2a9c1d-7b4", "status": "failed", "model": "google/nano-banana-2/text-to-image", "type": "image_generate", "error": "generation failed: upstream provider unavailable", "cost": "0.000000", "timestamp": 1778217000 } ``` Webhook delivery uses a 30 second HTTP timeout. A delivery that fails or returns a non-2xx status is retried up to 5 attempts, starting 30 seconds later and doubling each time. ### Verify the Signature Find your webhook secret in the [dashboard](https://eggapi.ai/dashboard), then compare signatures over the raw request body before parsing it: ```javascript import crypto from "node:crypto"; function verifyEggApiWebhook(rawBody, timestamp, signature, secret) { const expected = "sha256=" + crypto .createHmac("sha256", secret) .update(`${timestamp}.${rawBody}`) .digest("hex"); return signature.length === expected.length && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); } ``` Reject requests whose `X-EggAPI-Timestamp` is far from the current time to prevent replays. ## Polling Helper ```javascript async function waitForTask(taskId, apiKey, timeoutMs = 300000) { const start = Date.now(); while (Date.now() - start < timeoutMs) { const response = await fetch(`https://api.eggapi.ai/v1/tasks/${taskId}`, { headers: { "Authorization": `Bearer ${apiKey}` } }); const { data, error } = await response.json(); if (error) throw new Error(error.message); if (data.status === "completed") return data; if (data.status === "failed") throw new Error(data.error || "Task failed"); await new Promise((resolve) => setTimeout(resolve, 3000)); } throw new Error("Task timed out"); } ``` # Connect AI Agents (MCP) > Let Claude Code, Codex, Cursor, and other MCP clients generate images and videos through EggAPI Source: https://eggapi.ai/docs/mcp EggAPI runs a remote [Model Context Protocol](https://modelcontextprotocol.io) server. Any MCP client that supports Streamable HTTP can list models, start image and video tasks, and read their results with your API key. Usage is billed to the key's account exactly like `POST /v1/generate`. | Setting | Value | | --- | --- | | Endpoint | `https://api.eggapi.ai/mcp` | | Transport | Streamable HTTP | | Auth header | `Authorization: Bearer YOUR_API_KEY` | Create a key in the [dashboard](https://eggapi.ai/dashboard) and export it first: ```bash export EGGAPI_API_KEY="egg_..." ``` ## Client Setup ### Claude Code ```bash claude mcp add --transport http eggapi https://api.eggapi.ai/mcp \ --header "Authorization: Bearer $EGGAPI_API_KEY" ``` ### Codex Add to `~/.codex/config.toml`: ```toml [mcp_servers.eggapi] url = "https://api.eggapi.ai/mcp" bearer_token_env_var = "EGGAPI_API_KEY" ``` ### Cursor and other clients Add to your client's `mcp.json`: ```json { "mcpServers": { "eggapi": { "url": "https://api.eggapi.ai/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Step-by-step setup with a key generator is also on [eggapi.ai/connect](https://eggapi.ai/connect). ## Tools | Tool | Arguments | Returns | | --- | --- | --- | | `list_models` | `kind?` (`image` or `video`) | Model IDs with `kind`, `generation_type`, `unit_price_usd`, `unit_price_by_resolution`, and the tool that runs each one. | | `generate_image` | `model`, `prompt`, `images?`, `negative_prompt?`, `aspect_ratio?`, `resolution?`, `num_outputs?`, `parameters?`, `nsfw_filter?` | A `task_id`. `images` holds the source image URLs for edit models. | | `generate_video` | `model`, `prompt`, `duration`, `image?`, `negative_prompt?`, `aspect_ratio?`, `resolution?`, `parameters?`, `nsfw_filter?` | A `task_id`. `image` is the first frame URL for image-to-video models; `duration` is required. | | `get_task` | `task_id` | `status` (`pending`, `processing`, `completed`, `failed`), `done`, output `urls`, `cost`, and `error`. | The agent's workflow is: 1. Call `list_models` to pick a valid model ID. 2. Call `generate_image` or `generate_video`. It returns a `task_id` immediately; the output is not ready yet. 3. Poll `get_task` every 5 to 15 seconds until `done` is `true`. Images usually finish within a minute; videos usually take one to three minutes. Tasks created over MCP also appear in `GET /v1/tasks` and in your usage records. ## Dynamic UI tools The same server also provides `get_ui_catalog`, `render_ui`, `update_ui`, `get_ui_state`, `set_ui_values`, and `run_ui_action`: the agent composes a form page from a short JSON description, the user fills it in inside the conversation (clients that support MCP Apps) or in a browser, and the agent reads the result to continue. See [Dynamic UI](https://eggapi.ai/docs/dynamic-ui). ## Workflow Skills For complete workflows on top of these tools, such as e-commerce image sets, ad creatives, and short films, install the ready-made [workflow skills](https://eggapi.ai/docs/skills). # Dynamic UI > Agents compose a form page from a short JSON description and use one session in the conversation (MCP Apps), a browser, the CLI, or plain text Source: https://eggapi.ai/docs/dynamic-ui Dynamic UI lets an agent stop asking for parameters one by one and instead compose a page for the user's goal from pre-built components: for "make an ad image" the page shows the product image, brand, selling points, placement, style, model, cost estimate, and a generate button. The agent only writes a few KB of JSON; the renderer is compiled ahead of time, so opening a page generates no code and calls no model. - **One set of components**: ad images, product shots, image-to-video pages and anything else are composed from the same components and rendered by the same renderer. They are not fixed templates. - **One session**: MCP, the CLI and the browser read and write the same server-side session, so the agent can read what the user entered and the task results. - **No accidental charges**: creating or updating a page, choosing a model and editing fields never generate anything. Paid tasks start only when the user clicks a generate button (or the agent calls `run_ui_action` after the user explicitly agreed), and one click is never charged twice. ## Four ways in | Client capability | Entry | What the user sees | | --- | --- | --- | | Supports MCP Apps | The MCP tool result carries the UI | The page inline in the conversation | | MCP without MCP Apps | `browser_url` in the tool result | The same page in a browser | | No MCP, can run commands | The [`eggapi` CLI](#cli) | The agent creates the page by command and shares the link | | No browser, SSH, headless | `get_ui_state` lists fields, options and missing values | The agent asks in chat, then calls `set_ui_values` and `run_ui_action` | The browser page is a full entry point with the same features as the inline UI, including image upload. Tool results always carry text, structured data and the browser link, so clients without UI support can complete the whole flow. ## Client support As of 2026-10-28. "Docs only" means based on the client's official documentation, not run in that client; "Tested" means covered by this repository's automated tests. | Client | MCP connection | UI in the conversation | Status | | --- | --- | --- | --- | | Claude Code | HTTP or stdio | Its docs do not say the terminal renders MCP Apps; use the browser link | Setup docs only, not run in the client | | Codex CLI | HTTP or stdio | Its docs do not mention MCP Apps; use the browser link | Setup docs only, not run | | Gemini CLI | HTTP or stdio | Its docs describe text, image and audio content only; use the browser link | Setup docs only, not run | | OpenCode | HTTP or stdio | Its docs do not mention MCP Apps; use the browser link | Setup docs only, not run | | Claude / Claude Desktop, ChatGPT, VS Code GitHub Copilot, Goose, ... | HTTP | Listed as MCP Apps hosts in the MCP Apps docs | Not run in these hosts | | Official Go MCP SDK client | HTTP | — | Tested: tools, resource, capability detection, error structure | | Simulated MCP Apps host | postMessage | Yes | Tested: handshake, theme, narrow width, keyboard, submit and results (a simulated host is not a real host) | ## Setup Create an API key in the [dashboard](https://eggapi.ai/dashboard) and export it in the terminal that starts your agent: ```bash export EGGAPI_API_KEY="egg_..." ``` The remote MCP endpoint is `https://api.eggapi.ai/mcp` (Streamable HTTP, `Authorization: Bearer `). Clients already connected to [EggAPI MCP](https://eggapi.ai/docs/mcp) need no change: the new tools appear automatically. Clients without HTTP MCP can use `eggapi mcp` over stdio, which forwards messages to the same endpoint unchanged. ### Claude Code ```bash claude mcp add --transport http eggapi https://api.eggapi.ai/mcp \ --header "Authorization: Bearer $EGGAPI_API_KEY" ``` Over stdio: ```bash claude mcp add --env EGGAPI_API_KEY=$EGGAPI_API_KEY eggapi -- eggapi mcp ``` ### Codex CLI ```bash codex mcp add eggapi --url https://api.eggapi.ai/mcp --bearer-token-env-var EGGAPI_API_KEY ``` Or in `~/.codex/config.toml`: ```toml [mcp_servers.eggapi] url = "https://api.eggapi.ai/mcp" bearer_token_env_var = "EGGAPI_API_KEY" ``` ### Gemini CLI ```bash gemini mcp add --transport http --header "Authorization: Bearer $EGGAPI_API_KEY" eggapi https://api.eggapi.ai/mcp ``` Or in `~/.gemini/settings.json` (`httpUrl` is Streamable HTTP; `url` means SSE): ```json { "mcpServers": { "eggapi": { "httpUrl": "https://api.eggapi.ai/mcp", "headers": { "Authorization": "Bearer " } } } } ``` ### OpenCode In the project's `opencode.json` or `~/.config/opencode/opencode.json`: ```json { "mcp": { "eggapi": { "type": "remote", "url": "https://api.eggapi.ai/mcp", "headers": { "Authorization": "Bearer {env:EGGAPI_API_KEY}" } } } } ``` For stdio, use `{ "type": "local", "command": ["eggapi", "mcp"], "environment": { "EGGAPI_API_KEY": "egg_..." } }` instead. ### Clients that support MCP Apps Add EggAPI as described in [Connect AI agents](https://eggapi.ai/docs/mcp). Clients that only take a URL use the personal link from the dashboard, `https://api.eggapi.ai/mcp/k/`. ### Optional: skill [`eggapi-dynamic-ui`](https://eggapi.ai/skills/eggapi-dynamic-ui/SKILL.md) is a thin skill that only tells the agent when to use dynamic UI and in which order to call the tools. Everything works without it; install it like the [workflow skills](https://eggapi.ai/docs/skills). ## Agent workflow 1. Call `get_ui_catalog` once for the component contract. Pass `example` (`ad_image`, `product_main_image`, `image_to_video`) for a reference page. 2. Choose the fewest suitable components, write the page description and call `render_ui`. Use `values` to pre-fill what the conversation already tells you. 3. Give the user `browser_url`. Clients that support MCP Apps also show the page inline. 4. When the user says they are done, call `get_ui_state` for their values, missing fields, cost estimate and task results. 5. When the user wants the page changed ("add a copy field", "switch to a video ad", "hide the model choice"), call `update_ui` with the complete new description and `base_revision`. 6. Call `run_ui_action` only after the user explicitly agreed to the estimated cost, and pass the amount they agreed to as `expected_cost_usd`. The agent never writes HTML, CSS or React, installs dependencies, starts servers or runs browser tests. ## Page description (UI Schema 1.0) ```json { "schema_version": "1.0", "page": { "id": "image_to_video", "title": "Image to video" }, "initial_values": { "aspect_ratio": "9:16", "duration": 5 }, "actions": [ { "id": "animate", "type": "generate", "params": { "model": { "field": "model" }, "prompt": { "field": "motion" }, "images": { "field": "first_frame" }, "aspect_ratio": { "field": "aspect_ratio" }, "resolution": { "field": "resolution" }, "duration": { "field": "duration" } } } ], "root": { "id": "root", "type": "stack", "children": [ { "id": "first_frame", "type": "image_input", "props": { "label": "First frame", "required": true } }, { "id": "motion", "type": "textarea", "props": { "label": "Motion", "required": true } }, { "id": "aspect_ratio", "type": "aspect_ratio_picker", "props": { "label": "Aspect ratio", "options": ["9:16", "16:9", "1:1"] } }, { "id": "duration", "type": "number_input", "props": { "label": "Duration", "required": true, "min": 1, "max": 600, "unit": "s" } }, { "id": "model", "type": "model_picker", "props": { "label": "Video model", "required": true, "kind": "video", "generation_types": ["image-to-video"] } }, { "id": "resolution", "type": "select", "visible_when": { "field": "model", "op": "model_has_resolutions" }, "props": { "label": "Resolution", "options_source": { "source": "model_resolutions", "model_field": "model" } } }, { "id": "cost", "type": "cost_estimate", "props": { "action": "animate" } }, { "id": "generate", "type": "generate_button", "props": { "action": "animate", "label": "Generate video", "confirm": true } }, { "id": "status", "type": "task_status", "props": { "action": "animate" } }, { "id": "preview", "type": "video_preview", "props": { "action": "animate" } } ] } } ``` | Field | Meaning | | --- | --- | | `schema_version` | Required; only `"1.0"` is supported. Other versions return `unsupported_schema_version`. | | `page` | `id` (lowercase letters, digits, underscores), `title`, optional `description`. | | `root` | Root of the component tree; must be a layout component. | | `initial_values` | Starting values keyed by field id, checked against each field's type. | | `actions` | Pre-registered actions and their parameter bindings, at most 8. | Every component node has a stable `id`, a `type` and `props`, and optionally `visible_when` and `children`. Input components edit the field named by `field`, which defaults to the `id`. Keep ids unchanged when updating a page and the user's input is preserved. Limits: at most 64 KB of JSON, 150 components, 10 levels of nesting and 4 levels of condition nesting. A page description is data only: no HTML, scripts, code URLs or backend tool names, and components and actions can only reference names in the catalog. ### Components | Component | Category | Value | Main props | | --- | --- | --- | --- | | `stack` | layout | — | `gap` (sm/md/lg), `direction` (vertical/horizontal) | | `grid` | layout | — | `columns` (1-4, one column on narrow screens), `gap` | | `section` | layout | — | `title`, `description` | | `text_input` | input | string | `label`, `placeholder`, `help`, `required`, `max_length` | | `textarea` | input | string | as above, plus `rows` | | `select` | input | string | `options` (`[{value,label}]`) or `options_source`, exactly one | | `segmented_control` | input | string | `options` (2-6) | | `number_input` | input | number | `min`, `max`, `step`, `integer`, `unit` | | `image_input` | input | image_list | `max_images` (1-8); upload in the browser, image links elsewhere | | `model_picker` | business | string | `kind` (image/video), `generation_types`, `show_price`; models and prices come from the backend | | `aspect_ratio_picker` | business | string | `options` (subset of 1:1, 3:4, 4:3, 9:16, 16:9, 21:9) | | `cost_estimate` | business | — | `action`; live prices, same formula as the server's balance hold | | `generate_button` | business | — | `action`, `label`, `confirm`; the only component that submits paid work | | `task_status` | business | — | `action`; queued/running/done/failed, elapsed time, actual cost, no invented progress percentage | | `image_gallery` | business | — | `action`, `columns` | | `video_preview` | business | — | `action` | The full prop types, defaults and ranges are whatever `get_ui_catalog` (or `GET https://api.eggapi.ai/v1/ui/catalog`) returns; it reads the same registry the server validates with. ### Conditions `visible_when` shows or hides a component. Hidden fields are neither required nor submitted. ```json { "field": "background", "op": "eq", "value": "custom" } { "all": [ { "field": "mode", "op": "eq", "value": "video" }, { "field": "model", "op": "model_requires_image" } ] } ``` | Operator | Value | Meaning | | --- | --- | --- | | `eq`, `neq` | scalar | equals, differs | | `in`, `not_in` | list of scalars | one of, none of | | `empty`, `not_empty` | none | filled in or not | | `gt`, `gte`, `lt`, `lte` | number | `number_input` fields only | | `model_kind_eq` | `image` or `video` | kind of the selected model | | `model_generation_type_in` | list of generation types | generation type of the selected model | | `model_requires_image` | none | the selected model needs an input image | | `model_has_resolutions` | none | the selected model is priced per resolution | Conditions combine only with `all`, `any` and `not`; there are no expressions or scripts. ### Data sources `options_source` of a `select` currently supports `{"source": "model_resolutions", "model_field": ""}`: the resolutions the selected model is priced for, cheapest first. When the model declares none, the list is empty and the model's default is used. ### Actions The only action type is `generate`; it creates an image or video task depending on the selected model. Each parameter takes one binding: | Binding | Example | Meaning | | --- | --- | --- | | `field` | `{"field": "model"}` | a field's value; the component must be compatible | | `value` | `{"value": "bytedance/seedance-2.5/image-to-video"}` | a constant, e.g. a fixed model after "hide the model choice" | | `template` | `{"template": "Brand: {brand}\nSelling points: {selling_points}"}` | combines fields into text; a line with an empty placeholder is dropped; `{{` and `}}` are literal braces | | Param | Required | Meaning | | --- | --- | --- | | `model` | yes | `model_picker` field or constant | | `prompt` | yes | text field, template or constant | | `negative_prompt` | no | as above | | `images` | no | `image_input` field; references for image models, first frame (one image) for video models | | `aspect_ratio` | no | ratio picker, select or constant (default 16:9) | | `resolution` | no | must be a resolution the model is priced for | | `num_outputs` | no | 1-16, image models only | | `duration` | for video | 1-600 s, billed per second; the backend publishes no per-model range, so none is assumed | On submit the server checks the inputs against the selected model: image-to-* models need an image, text-to-* models refuse images, video models take one first frame, and the resolution must be priced. ### Errors Every validation problem comes with a JSON pointer path, a code and a hint, so an agent can fix it directly: ```json { "error": { "code": "SCHEMA_INVALID", "issues": [ { "path": "/root/children/2/type", "code": "unknown_component", "message": "unknown component \"html\"", "hint": "allowed: stack, grid, ..." } ] } } ``` | Code | Meaning | | --- | --- | | `SCHEMA_INVALID` | invalid page description; `issues` lists each problem | | `REVISION_CONFLICT` | the page changed since you read it; the error carries the current session | | `ACTION_NOT_READY` | required values missing, not valid for the model, or the estimate changed (`estimate_changed`); `issues` points at the fields | | `TOO_MANY_SESSIONS` | an account keeps at most 200 unexpired sessions; reuse a page with `update_ui` | | `INSUFFICIENT_BALANCE`, `CONTENT_BLOCKED` | not enough balance, or blocked by the NSFW filter; nothing is charged | | `NOT_FOUND` | the session does not exist, expired, or belongs to another account | ## Sessions and updates The server keeps one session per page: `session_id`, `schema_version`, `revision` (bumped on every change), `schema_revision` (the revision of the last page description change), `fingerprint` (changes with the revision and with live model prices), the page description, values, submissions, status and expiry. A session belongs to the EggAPI account that created it and expires after 7 days without changes; expired sessions are deleted the next time that account creates a page, and an account keeps at most 200 unexpired sessions. `update_ui` rules: - `base_revision` must equal the current `schema_revision`, otherwise you get `REVISION_CONFLICT` and nothing is overwritten. The user editing values meanwhile is not a conflict. - A value is kept when its field id and value type are unchanged and it is still valid for the new field (`reconcile.preserved`). - When the type changed or the value is no longer valid (a removed option, an image model after switching to a video picker) it is reset (`reconcile.reset`); removed fields are listed with their previous value in `reconcile.removed`. Stale values are never submitted silently. - An open page picks up the new version within seconds and updates in place: text being typed and focus are kept. ## Browser page `browser_url` looks like `https://eggapi.ai/ui/`. It contains no API key; opening it requires signing in to the same EggAPI account, so it works on any device. Links created by agents on a laptop, a remote server, over SSH or in a container all point at the EggAPI website, not at the agent machine's localhost. Without a GUI, copy the link to any browser; the CLI never opens one. The page saves input automatically and checks for updates every few seconds; while a task runs it refreshes at the task API's polling limits (5 s for images, 10 s for videos), without the agent polling. When the user submits in the browser, the result is written to the session, but a browser cannot wake an agent in a terminal. Tell the agent you are done and it reads the result with `get_ui_state`. MCP Apps hosts that support `ui/update-model-context` also receive the latest state in the agent's context. ## CLI `eggapi` is a standard-library-only command-line tool that shares the server's validation, sessions and account scoping with MCP. There are no prebuilt releases yet; build it from source with repository access (Go 1.23+): ```bash git clone https://github.com/danaigc/eggapi && cd eggapi/backend go build -o ~/.local/bin/eggapi ./cmd/eggapi ``` | Command | Does | | --- | --- | | `eggapi ui catalog --json` | the component contract; `--example ad_image` returns a reference page | | `eggapi ui create --schema-file page.json --json` | create a page; `-` reads stdin | | `eggapi ui update --schema-file page.json --base-revision N --json` | update a page | | `eggapi ui state --json` | values, missing fields, actions and task results; `--full` adds the page description | | `eggapi ui set --values '{"brand":"Acme"}' --json` | set field values | | `eggapi ui run --schema-revision N --expected-cost USD --submission-id S --json` | run the paid action; refused if the estimate differs from `--expected-cost`; retry with the same `--submission-id` and it is never charged twice (network or server errors return that id) | | `eggapi ui wait --json` | wait for the latest task at 5/10 s intervals | | `eggapi mcp` | MCP server over stdio | With `--json`, stdout holds exactly one JSON document and logs go to stderr. Errors print `{"error": {"code", "message", "http_status", "details"}}`. Exit codes: `0` ok, `2` usage, `3` rejected (validation, conflict, balance, ...), `4` authentication, `5` network or server, `6` wait timeout. Credentials come from `EGGAPI_API_KEY`; `EGGAPI_API_BASE` overrides the API URL. ## Without a GUI Without a browser, the agent completes the same flow in text: 1. Create the page with `render_ui` (or reuse one). 2. `get_ui_state` returns each field's `label`, whether it is required, missing and visible, its value, and the `options` it currently allows (models, resolutions, ratios, ...). 3. Ask the user in chat and write the answers with `set_ui_values`; rejected values come back with reasons. 4. Show the user `actions[].estimated_cost_usd` and call `run_ui_action` only after they agree, with `expected_cost_usd` set to the amount they agreed to. 5. Read the task status, output URLs and actual cost later with `get_ui_state`. ## Billing and security - The estimate uses the same formula as the balance hold taken when a task is created: per image or per second of video, at the model's resolution price. On submit the server recomputes it from the actual parameters; the task is settled at its real cost and refunded if it fails. - Each click carries a `submission_id`. The server deduplicates on it and derives a fixed task id from it, so retries and double clicks never create a second task. When the outcome is unknown (network failure, gateway error), the page reuses the same id on the next click and only looks up that submission. - A click submits every field value shown on screen together with the estimate on the button. If the server's estimate differs (prices changed, or values were edited elsewhere), or the submit would invalidate a chosen value (a resolution the new model does not offer), the run is refused with the reason instead of charging an amount the user did not see. - Once generation starts it is detached from the request: closing the page or a CLI timeout cannot lose the record of a submission whose balance is held. A submission the server stopped in the middle of is completed from the task record the next time the session is read. - Generations submitted from the browser page always use the NSFW filter, like the playground; submissions with an API key (MCP, CLI) follow the key's request. - The API key stays in the agent's client configuration and on the server; it never appears in page descriptions, the browser page or links. The MCP Apps UI calls tools through its host; the browser page uses the website sign-in. ## Limitations - The four CLIs do not show the inline UI in the terminal (their docs say nothing about it); use the browser link or the text flow. - The MCP Apps UI runs in the host's sandbox: it cannot upload local files (image links only; upload in the browser page), and output images or videos from domains not listed in the server's `UI_MCP_RESOURCE_DOMAINS` appear as links instead of previews. - The MCP server is stateless and cannot see capabilities declared at `initialize`. When a client declares MCP Apps support in each request's `_meta`, results say `ui_mode: "embedded"`; otherwise they say `link` and lead with the browser link, and hosts that support MCP Apps still render the UI. - Submitting in the browser does not notify the agent; the user tells it in the conversation. - Aspect ratios are the six documented ones because the backend does not publish per-model support; video duration is only checked against the API's 1-600 s. - There is no "rewrite copy / improve prompt" action yet: the agent writes copy in the conversation and puts it on the page through `values` or `update_ui`. # Workflow Skills > Ready-made Claude Code and Codex skills for e-commerce images, ad creatives, and short films, built on the EggAPI MCP tools Source: https://eggapi.ai/docs/skills Workflow skills are ready-made instructions for agent CLIs. Each one teaches Claude Code or Codex a complete production workflow on top of the [EggAPI MCP tools](https://eggapi.ai/docs/mcp): collect the brief, show a plan with an estimated cost, upload local files, generate, check the results, and save them to disk. Use them as they are, or edit them into your own process. | Skill | For | What it makes | | --- | --- | --- | | [`eggapi-ecommerce`](https://eggapi.ai/skills/eggapi-ecommerce/SKILL.md) | E-commerce sellers | A listing image set from real product photos: white-background main image, lifestyle scenes, selling-point images, close-ups, and an optional product video, sized for Amazon, Shopify, Taobao/Tmall, TikTok Shop, Douyin, and Xiaohongshu. | | [`eggapi-ad-creatives`](https://eggapi.ai/skills/eggapi-ad-creatives/SKILL.md) | Advertisers | Several ad concepts built on different angles, each in every placement size, optional video ads, and a `manifest.csv` for A/B tests. | | [`eggapi-short-film`](https://eggapi.ai/skills/eggapi-short-film/SKILL.md) | Short-film creators | A script and shot list, character sheets and keyframes that keep characters consistent, one clip per shot, and a final cut joined with ffmpeg. | ## Before You Start 1. Connect EggAPI to your agent as described in [Connect AI Agents (MCP)](https://eggapi.ai/docs/mcp). 2. Export your API key in the shell your agent starts from. The skills use it to upload local files with [`POST /v1/uploads`](https://eggapi.ai/docs/uploads): ```bash export EGGAPI_API_KEY="egg_..." ``` 3. Optional: install `ffmpeg` so `eggapi-short-film` can join the clips into one film. ## Install A skill is a folder with a `SKILL.md` file. Claude Code reads skills from `~/.claude/skills/`, Codex from `~/.codex/skills/`. Install all three: ### Claude Code ```bash for s in eggapi-ecommerce eggapi-ad-creatives eggapi-short-film; do mkdir -p ~/.claude/skills/$s curl -fsSL https://eggapi.ai/skills/$s/SKILL.md -o ~/.claude/skills/$s/SKILL.md done ``` ### Codex ```bash for s in eggapi-ecommerce eggapi-ad-creatives eggapi-short-film; do mkdir -p ~/.codex/skills/$s curl -fsSL https://eggapi.ai/skills/$s/SKILL.md -o ~/.codex/skills/$s/SKILL.md done ``` To install only some of them, keep just their names after `for s in`. To share the skills with a team in Claude Code, put the folders in `.claude/skills/` inside the project repository instead. Start a new agent session after installing so it loads the skills. ## Use Describe the job in your own words and the agent picks the matching skill. You can also name the skill: ```text Use eggapi-ecommerce: turn ./photos/bottle.jpg into an Amazon main image and three lifestyle shots. ``` ```text Make 3 ad concepts for our new espresso machine for TikTok and Instagram, with video versions. ``` ```text Make a 40-second vertical short film: a cat finds its way home through Tokyo on a rainy night. ``` Every skill stops after the plan and shows the estimated cost before it generates anything. Images and video seconds are billed to the key's account at the same prices as the API. Finished files are saved to `eggapi-output//` in the current directory. ## Customize Each skill is one Markdown file written in plain language, so you can change it like a document: - Swap the default models for any ID from [Models](https://eggapi.ai/docs/models). - Add your own platforms, sizes, or brand rules such as colors, fonts, and words to avoid. - Change the default set, for example five lifestyle scenes instead of three. - Change where the files are saved. Running the install command again replaces the files with the latest version. To keep your edits, copy the skill to a new folder first and set the `name` line at the top of its `SKILL.md` to the new folder name: ```bash cp -r ~/.claude/skills/eggapi-ecommerce ~/.claude/skills/my-shop-images ``` ```yaml name: my-shop-images ``` Then delete the original folder, or reword its `description`, so the agent does not have two skills for the same job. # Errors > EggAPI error response format and common failure cases Source: https://eggapi.ai/docs/errors EggAPI returns a consistent response envelope: ```json { "data": null, "error": { "code": "VALIDATION_ERROR", "message": "model bytedance/seedance-2.5/text-to-video requires duration (in seconds) for video generation" } } ``` Successful responses use the same envelope with `error: null`. ## Error Codes | HTTP status | Code | Typical cause | | --- | --- | --- | | `400` | `BAD_REQUEST` | Missing path/query data or malformed request. | | `400` | `VALIDATION_ERROR` | JSON body failed validation. | | `400` | `CONTENT_BLOCKED` | `nsfw_filter` is on and the prompt or an input image did not pass the NSFW filter. Not charged. | | `401` | `UNAUTHORIZED` | Missing, malformed, inactive, expired, or invalid credentials. | | `403` | `FORBIDDEN` | User account is suspended or the session lacks permission. | | `403` | `INSUFFICIENT_BALANCE` | Balance cannot cover the task's estimated cost, which is held when the task is created. Top up in the dashboard. | | `404` | `NOT_FOUND` | Task or dashboard resource was not found, or it belongs to another account. | | `429` | `RATE_LIMITED` | API key or IP rate limit was exceeded. | | `500` | `INTERNAL_ERROR` | Backend, database, queue, or storage failure. | | `502` | `UPSTREAM_ERROR` | Upstream provider returned a gateway failure. | | `503` | `SERVICE_UNAVAILABLE` | Service temporarily unavailable. | | `503` | `MODERATION_UNAVAILABLE` | `nsfw_filter` is on and the filter could not give a verdict. Nothing was generated; retry shortly. | ## Validation Errors `POST /v1/generate` checks: - `model`: required; must be a published model ID (see [Models](https://eggapi.ai/docs/models)) - `prompt`: required, 1 to 100000 characters - `negative_prompt`: up to 1000 characters - `num_outputs`: 1 to 16 - `resolution`: one of the model's priced resolutions (see [Models](https://eggapi.ai/docs/models)) - `duration`: required for video models; the published video models accept 4 to 15 seconds - `image_urls`: up to 32 valid URLs; required for edit and image-to-video models - `webhook_url`: valid URL, up to 2048 characters - `nsfw_filter`: boolean Missing duration on a video model: ```json { "data": null, "error": { "code": "VALIDATION_ERROR", "message": "model bytedance/seedance-2.5/text-to-video requires duration (in seconds) for video generation" } } ``` Missing input image on an edit model: ```json { "data": null, "error": { "code": "VALIDATION_ERROR", "message": "model google/nano-banana-pro/edit requires image_urls or parameters.images for image-to-image" } } ``` A model ID that is not published returns `400 VALIDATION_ERROR` with a message that starts with `unsupported model`. Check the ID against the [model list](https://eggapi.ai/docs/models). ## Authentication Errors Missing header: ```json { "data": null, "error": { "code": "UNAUTHORIZED", "message": "Missing Authorization header" } } ``` Invalid format: ```json { "data": null, "error": { "code": "UNAUTHORIZED", "message": "Invalid Authorization format, expected 'Bearer '" } } ``` ## Task Failures A failed generation task is returned as successful HTTP `200` from `GET /v1/tasks/{id}` because the task lookup succeeded. The failure is represented inside `data.status` and `data.error`. ```json { "data": { "id": "gen_3f2a9c1d-7b4", "status": "failed", "model": "google/nano-banana-2/text-to-image", "type": "image_generate", "error": "generation failed: upstream provider unavailable", "cost": "$0.00", "created_at": "2026-05-08T10:30:00Z", "started_at": "2026-05-08T10:30:01Z", "completed_at": "2026-05-08T10:30:12Z" }, "error": null } ``` ## Handling Pattern ```javascript async function eggapi(request) { const response = await fetch(request); const body = await response.json(); if (body.error) { throw new Error(`${body.error.code}: ${body.error.message}`); } return body.data; } ``` For task polling, check both the HTTP response envelope and the task status: ```javascript const task = await eggapi(`https://api.eggapi.ai/v1/tasks/${taskId}`); if (task.status === "failed") { throw new Error(task.error || "EggAPI task failed"); } ``` # API Reference > Reference conventions for the EggAPI public API Source: https://eggapi.ai/docs/api-reference ## Base URL ```text https://api.eggapi.ai ``` ## Authentication Use an API key from the dashboard: ```text Authorization: Bearer YOUR_API_KEY ``` ## Models Pass a published model ID, such as `google/nano-banana-2/text-to-image` or `bytedance/seedance-2.5/text-to-video`, as `model`. See [Models](https://eggapi.ai/docs/models) for the full list. ## Request Format - Use HTTPS. - Send JSON bodies with `Content-Type: application/json`, except `POST /v1/uploads`, which takes `multipart/form-data`. - Include `Authorization: Bearer YOUR_API_KEY`. ## Response Envelope Success: ```json { "data": {}, "error": null } ``` Error: ```json { "data": null, "error": { "code": "VALIDATION_ERROR", "message": "request validation failed" } } ``` ## Status Codes | Status | Meaning | | --- | --- | | `200` | Request succeeded. | | `201` | Files were uploaded. | | `202` | Async generation task was created. | | `400` | Bad request or validation error. | | `401` | Missing or invalid credentials. | | `403` | Forbidden or insufficient balance. | | `404` | Resource not found. | | `429` | Rate limited. | | `500` | Internal backend error. | | `502` | Upstream provider error. | | `503` | Service unavailable. | ## Pagination List endpoints use: | Parameter | Default | Max | | --- | --- | --- | | `page` | `1` | - | | `per_page` | `20` | `100` | Paginated responses return `data.items` and `data.pagination`. ## Endpoints | Method | Path | Description | | --- | --- | --- | | `POST` | `/v1/generate` | Create an image or video generation task. Body fields: [Models](https://eggapi.ai/docs/models#common-parameters). | | `POST` | `/v1/uploads` | Upload input images, videos, or audio and get public URLs. See [Uploads](https://eggapi.ai/docs/uploads). | | `GET` | `/v1/tasks/{id}` | Get one task with its status and output. See [Async Tasks](https://eggapi.ai/docs/async-tasks#poll-a-task). | | `GET` | `/v1/tasks` | List your tasks, newest first. See [Async Tasks](https://eggapi.ai/docs/async-tasks#list-tasks). | | `GET` | `/v1/usage` | List usage records. See [Usage](#usage). | | `GET` | `/v1/usage/summary` | Usage totals grouped by model. See [Usage](#usage). | | `POST` | `/mcp` | [MCP server](https://eggapi.ai/docs/mcp) for AI agents. | ## Usage `GET /v1/usage` returns usage records under `data.items`, newest first, paginated with `page` and `per_page`. Each record has `id`, `task_id`, `model`, `type`, `units`, `unit_cost`, `total_cost`, `status`, and `created_at`. `GET /v1/usage/summary` returns one row per model with `model`, `total_units`, `total_cost`, and `request_count`. See the example in the [Quickstart](https://eggapi.ai/docs/quickstart#5-check-usage). ## OpenAPI The [OpenAPI spec](https://eggapi.ai/openapi.json) describes every endpoint, request body, and response schema. # Model Catalog Source: https://eggapi.ai/models Live list of the 18 models published on EggAPI, last published Mon Oct 26 2026 12:41:44 GMT+0000 (Coordinated Universal Time). Pass the model ID as `model` to `POST https://api.eggapi.ai/v1/generate`. - Image models bill per output image and video models bill per second of video, at the price of the requested `resolution`. When `resolution` is omitted, the base price applies; an unlisted resolution is rejected. - Options not listed as top-level fields go in the `parameters` object. ## Seedream 5.0 Pro (text-to-image) - Model ID: `bytedance/seedream-v5.0-pro` - Page: https://eggapi.ai/models/bytedance/seedream-v5.0-pro - Kind: image · generation type: text-to-image · task type: `image_generate` - Price: $0.1125 per image base; by resolution: 1k $0.05625, 2k $0.1125 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k - `num_outputs`: number of images, default 1; each returned image is billed - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "bytedance/seedream-v5.0-pro", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 } ``` ## Seedream 5.0 Pro (image-to-image) - Model ID: `bytedance/seedream-v5.0-pro/edit` - Page: https://eggapi.ai/models/bytedance/seedream-v5.0-pro/edit - Kind: image · generation type: image-to-image · task type: `image_edit` - Price: $0.1125 per image base; by resolution: 1k $0.05625, 2k $0.1125 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k - `image_urls`: required, 1 to 8 source image URLs - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "bytedance/seedream-v5.0-pro/edit", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Seedream 4.5 (text-to-image) - Model ID: `bytedance/seedream-v4.5` - Page: https://eggapi.ai/models/bytedance/seedream-v4.5 - Kind: image · generation type: text-to-image · task type: `image_generate` - Price: $0.05 per image base; by resolution: 1k $0.05, 2k $0.05, 4k $0.05 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k, 4k - `num_outputs`: number of images, default 1; each returned image is billed - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "bytedance/seedream-v4.5", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 } ``` ## Seedream 4.5 (image-to-image) - Model ID: `bytedance/seedream-v4.5/edit` - Page: https://eggapi.ai/models/bytedance/seedream-v4.5/edit - Kind: image · generation type: image-to-image · task type: `image_edit` - Price: $0.05 per image base; by resolution: 1k $0.05, 2k $0.05, 4k $0.05 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k, 4k - `image_urls`: required, 1 to 8 source image URLs - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "bytedance/seedream-v4.5/edit", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Nano Banana Pro (text-to-image) - Model ID: `google/nano-banana-pro/text-to-image` - Page: https://eggapi.ai/models/google/nano-banana-pro/text-to-image - Kind: image · generation type: text-to-image · task type: `image_generate` - Price: $0.0225 per image base; by resolution: 1k $0.0225, 2k $0.0225, 4k $0.03375 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k, 4k - `num_outputs`: number of images, default 1; each returned image is billed - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "google/nano-banana-pro/text-to-image", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 } ``` ## Nano Banana Pro (image-to-image) - Model ID: `google/nano-banana-pro/edit` - Page: https://eggapi.ai/models/google/nano-banana-pro/edit - Kind: image · generation type: image-to-image · task type: `image_edit` - Price: $0.0225 per image base; by resolution: 1k $0.0225, 2k $0.0225, 4k $0.03375 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k, 4k - `image_urls`: required, 1 to 8 source image URLs - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "google/nano-banana-pro/edit", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Nano Banana 2 (text-to-image) - Model ID: `google/nano-banana-2/text-to-image` - Page: https://eggapi.ai/models/google/nano-banana-2/text-to-image - Kind: image · generation type: text-to-image · task type: `image_generate` - Price: $0.016875 per image base; by resolution: 0.5k $0.016875, 1k $0.0135, 2k $0.01575, 4k $0.02025 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 0.5k, 1k, 2k, 4k - `num_outputs`: number of images, default 1; each returned image is billed - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "google/nano-banana-2/text-to-image", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 } ``` ## Nano Banana 2 (image-to-image) - Model ID: `google/nano-banana-2/edit` - Page: https://eggapi.ai/models/google/nano-banana-2/edit - Kind: image · generation type: image-to-image · task type: `image_edit` - Price: $0.016875 per image base; by resolution: 0.5k $0.016875, 1k $0.0135, 2k $0.01575, 4k $0.02025 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 0.5k, 1k, 2k, 4k - `image_urls`: required, 1 to 8 source image URLs - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "google/nano-banana-2/edit", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## GPT Image 2 (text-to-image) - Model ID: `openai/gpt-image-2/text-to-image` - Page: https://eggapi.ai/models/openai/gpt-image-2/text-to-image - Kind: image · generation type: text-to-image · task type: `image_generate` - Price: $0.009563 per image base; by resolution: 1k $0.009563, 2k $0.016875, 4k $0.02475 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k, 4k - `num_outputs`: number of images, default 1; each returned image is billed - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "openai/gpt-image-2/text-to-image", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "num_outputs": 1 } ``` ## GPT Image 2 (image-to-image) - Model ID: `openai/gpt-image-2/edit` - Page: https://eggapi.ai/models/openai/gpt-image-2/edit - Kind: image · generation type: image-to-image · task type: `image_edit` - Price: $0.009563 per image base; by resolution: 1k $0.009563, 2k $0.016875, 4k $0.02475 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 1k, 2k, 4k - `image_urls`: required, 1 source image URLs - `parameters.output_format`: png, jpeg, webp Example request body: ```json { "model": "openai/gpt-image-2/edit", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "1k", "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Seedance 2.5 (text-to-video) - Model ID: `bytedance/seedance-2.5/text-to-video` - Page: https://eggapi.ai/models/bytedance/seedance-2.5/text-to-video - Kind: video · generation type: text-to-video · task type: `video_generate` - Price: $0.250455 per second base; by resolution: 480p $0.111339, 720p $0.250455, 1080p $0.619986 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 480p, 720p, 1080p - `duration`: required, 4 to 15 seconds - `parameters.reference_images`: array of reference image URLs - `parameters.reference_videos`: array of reference video URLs - `parameters.reference_audios`: array of reference audio URLs - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "bytedance/seedance-2.5/text-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5 } ``` ## Seedance 2.5 (image-to-video) - Model ID: `bytedance/seedance-2.5/image-to-video` - Page: https://eggapi.ai/models/bytedance/seedance-2.5/image-to-video - Kind: video · generation type: image-to-video · task type: `video_generate` - Price: $0.250455 per second base; by resolution: 480p $0.111339, 720p $0.250455, 1080p $0.619986 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 480p, 720p, 1080p - `duration`: required, 4 to 15 seconds - `image_urls`: required, one URL with the first frame - `parameters.last_image`: URL of the last frame - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "bytedance/seedance-2.5/image-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5, "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Seedance 2.0 (text-to-video) - Model ID: `bytedance/seedance-2.0/text-to-video` - Page: https://eggapi.ai/models/bytedance/seedance-2.0/text-to-video - Kind: video · generation type: text-to-video · task type: `video_generate` - Price: $0.15975 per second base; by resolution: 480p $0.07425, 720p $0.15975, 1080p $0.3987, 4k $0.81225 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 480p, 720p, 1080p, 4k - `duration`: required, 4 to 15 seconds - `parameters.reference_images`: array of reference image URLs - `parameters.reference_videos`: array of reference video URLs - `parameters.reference_audios`: array of reference audio URLs - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "bytedance/seedance-2.0/text-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5 } ``` ## Seedance 2.0 (image-to-video) - Model ID: `bytedance/seedance-2.0/image-to-video` - Page: https://eggapi.ai/models/bytedance/seedance-2.0/image-to-video - Kind: video · generation type: image-to-video · task type: `video_generate` - Price: $0.15975 per second base; by resolution: 480p $0.07425, 720p $0.15975, 1080p $0.3987, 4k $0.81225 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 480p, 720p, 1080p, 4k - `duration`: required, 4 to 15 seconds - `image_urls`: required, one URL with the first frame - `parameters.last_image`: URL of the last frame - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "bytedance/seedance-2.0/image-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5, "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Wan 3.0 (text-to-video) - Model ID: `alibaba/wan-3.0/text-to-video` - Page: https://eggapi.ai/models/alibaba/wan-3.0/text-to-video - Kind: video · generation type: text-to-video · task type: `video_generate` - Price: $0.25 per second base; by resolution: 480p $0.0625, 720p $0.125, 1080p $0.25 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 480p, 720p, 1080p - `duration`: required, 4 to 15 seconds - `parameters.reference_images`: array of reference image URLs - `parameters.reference_videos`: array of reference video URLs - `parameters.reference_audios`: array of reference audio URLs - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "alibaba/wan-3.0/text-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5 } ``` ## Wan 3.0 (image-to-video) - Model ID: `alibaba/wan-3.0/image-to-video` - Page: https://eggapi.ai/models/alibaba/wan-3.0/image-to-video - Kind: video · generation type: image-to-video · task type: `video_generate` - Price: $0.25 per second base; by resolution: 480p $0.0625, 720p $0.125, 1080p $0.25 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 480p, 720p, 1080p - `duration`: required, 4 to 15 seconds - `image_urls`: required, one URL with the first frame - `parameters.last_image`: URL of the last frame - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "alibaba/wan-3.0/image-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5, "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ``` ## Wan 2.7 (text-to-video) - Model ID: `alibaba/wan-2.7/text-to-video` - Page: https://eggapi.ai/models/alibaba/wan-2.7/text-to-video - Kind: video · generation type: text-to-video · task type: `video_generate` - Price: $0.0747 per second base; by resolution: 720p $0.0747, 1080p $0.1233 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 720p, 1080p - `duration`: required, 4 to 15 seconds - `parameters.reference_images`: array of reference image URLs - `parameters.reference_videos`: array of reference video URLs - `parameters.reference_audios`: array of reference audio URLs - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "alibaba/wan-2.7/text-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5 } ``` ## Wan 2.7 (image-to-video) - Model ID: `alibaba/wan-2.7/image-to-video` - Page: https://eggapi.ai/models/alibaba/wan-2.7/image-to-video - Kind: video · generation type: image-to-video · task type: `video_generate` - Price: $0.0747 per second base; by resolution: 720p $0.0747, 1080p $0.1233 - `aspect_ratio`: 16:9, 9:16, 4:3, 3:4, 1:1, 21:9 (default 16:9) - `resolution`: 720p, 1080p - `duration`: required, 4 to 15 seconds - `image_urls`: required, one URL with the first frame - `parameters.last_image`: URL of the last frame - `parameters.enable_web_search`: boolean, let the model search the web - `parameters.generate_audio`: boolean, generate a soundtrack Example request body: ```json { "model": "alibaba/wan-2.7/image-to-video", "prompt": "a cracked obsidian egg leaking acid-green light, studio product shot", "aspect_ratio": "16:9", "resolution": "720p", "duration": 5, "image_urls": [ "https://file.eggapi.ai/uploads/image/your-user-id/input.png" ] } ```