LetzAI API Integration Skill
Overview
Helps you integrate the LetzAI public API for AI image and video generation, editing,
upscaling, asset uploads, and custom model (LoRA) training. Custom-trained models for
persons, objects and styles are referenced inside prompts with @modelname.
Authentication
- Base URL:
https://api.letz.ai - Auth:
Authorization: Bearer YOUR_API_KEY - Get an API key: letz.ai/subscription
- Swagger (source of truth): api.letz.ai/doc — machine-readable at
/doc-jsonand/doc-yaml
const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.LETZAI_API_KEY}`,
};
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['LETZAI_API_KEY']}",
}
Do not confuse the public API with the private one.
https://api.letz.aiis the public developer API described here.https://private-api.letz.aipowers the LetzAI web app and has different route names (/upscales,/image_completions,/video-edits). Those routes 404 on the public API.
Unknown-field rejection
The API validates request bodies strictly. Sending a field that is not in the schema
returns 400. In particular there is no negativePrompt, seed or aspectRatio on
POST /images — aspect ratio is expressed via width/height.
Core Workflows
1. Image Generation — POST /images
| Parameter | Type | Default | Notes |
|---|---|---|---|
prompt | string | — | Required. May contain @modelname tags. |
baseModel | string | account default | See model table below. |
mode | string | model default | Resolution tier — allowed values differ per model. |
width | int | 1600 | 480–2160 |
height | int | 1600 | 480–2160 |
quality | int | 2 | 1–6 |
creativity | int | 2 | 1–6 |
hasWatermark | bool | true | |
systemVersion | int | account default | 2 or 3 |
hideFromUserProfile | bool | false | |
webhookUrl | string | — | POSTed when the job finishes. |
organizationId | UUID | — | Bill credits to an org you belong to. |
Image models
mode is the resolution tier, and the accepted values are model-specific.
| Model | baseModel | mode values | Credits (generate) | Credits (edit) |
|---|---|---|---|---|
| Nano Banana Pro (Google) | gemini-3-pro-image | default (1K) · 2k (HD) · 4k | 80 / 160 / 240 | 80 / 160 / 240 |
| Nano Banana 2 (Google) | nbf-inferencesh | default (1K) · 2k (HD) · 4k | 40 / 80 / 160 | 50 / 100 / 150 |
| Nano Banana 2 Lite (Google) | nano-banana-2-lite | default (1K) | 20 | 25 |
| Seedream 5 Pro (ByteDance) | seedream-5-0-pro | 2k (HD) · 4k | 80 / 160 | 80 / 160 |
| Seedream 4.5 (ByteDance) | seedream-4-5-251128 | 2k (HD) · 4k | 80 / 160 | 80 / 160 |
| Flux 2 (Black Forest Labs) | flux2 | 1k · hd | 60 / 120 | 60 / 120 |
| GPT Image 2 (OpenAI) | gpt-image-2 | 1k · hd · 4k | 160 / 240 / 480 | 160 / 240 / 480 |
| WAN 2.7 Image Pro (Alibaba) | wan-2-7-image-pro | 1k · 2k | 10 | 10 |
Aliases are accepted, e.g. gemini-3-pro-image-preview still resolves to Nano Banana Pro.
The live catalogue with pricing lives at letz.ai/docs/models.json.
Workflow
POST /images- Read
idfrom the response - Poll
GET /images/{id}every 3 s - On
status === "ready", readimageVersions.original
See examples/image_generation.js.
2. Video Generation — POST /videos
| Parameter | Type | Notes |
|---|---|---|
prompt | string | Required. |
originalImageCompletionId | UUID | Animate a previously generated LetzAI image. |
imageUrl | string | Animate a public image URL. |
imageUrls | string[] | Multi-frame: [0] = first frame, [1] = last frame. |
prompts | object[] | Multi-shot storyboards (video-kling3): [{ prompt, duration }]. |
baseModel | string | Optional; settings.mode is the usual selector. |
width / height / resolution | number | Optional output sizing. |
settings | object | Model + duration + audio (below). |
webhookUrl | string | |
hidePrompt | bool | |
organizationId | UUID |
Image input is optional — omit all of originalImageCompletionId / imageUrl /
imageUrls for pure text-to-video.
settings
| Field | Notes |
|---|---|
mode | Video model key — see table. |
duration | Seconds, clamped to the model's allowed values. |
withSound | Enable native audio where supported. |
highQuality | Higher-resolution tier; usually doubles the price. |
resolution | "720p", "1080p", "4k" for per-second-priced models. |
Video models
Use the video- prefixed key as settings.mode.
| Model | settings.mode | Duration | Credits |
|---|---|---|---|
| Google Veo 3.1 | video-veo31 | 8 s (fixed) | 1500 · ×2 with audio · ×2 at 1080p |
| Kling V3 | video-kling3 | 3–15 s | 150 · 300 with audio |
| Kling V2.6 | video-kling26 | 5 or 10 s | 150 · ×2 with audio · ×2 at 1080p |
| WAN 2.5 | video-wan25 | 5 or 10 s | 110 · ×2 at 1080p (image-to-video only) |
| Seedance 2.0 | video-seedance2 | 4–15 s | per second: 105 @480p · 210 @720p · 500 @1080p · 1000 @4K (audio always on) |
| Seedance 2.0 Enterprise | video-seedance2-enterprise | 4–15 s | same as Seedance 2.0; requires organizationId |
| Gemini Omni Flash | video-gemini-omni | 3–10 s | 100 per second (audio always on) |
Workflow
POST /videos- Poll
GET /videos/{id}every 2–3 s - On
status === "ready", readvideoVersions.original
See examples/video_generation.py.
3. Image Editing — POST /image-edits
| Parameter | Type | Notes |
|---|---|---|
mode | string | Required. context (AI editing) or skin (skin fix). |
prompt | string | Edit instruction. May contain @modelname tags. |
imageUrl | string | Single source image URL. |
inputImageUrls | string[] | Multi-reference source images (up to 9 in practice). |
originalImageCompletionId | UUID | Edit a previously generated LetzAI image. |
originalImageCompletionIds | UUID[] | Several LetzAI images as sources. |
baseModel | string | Same identifiers as image generation. |
settings | object | { resolution, aspect_ratio, model } |
imageCompletionsCount | int | Variations to generate (1–5, default 1). Not used by skin. |
mask | string | Base64 mask, legacy inpainting only. |
width / height | number | Target dimensions. |
webhookUrl, organizationId, hidePrompt |
settings:
resolution:"2k"(HD) or"4k"(Ultra HD)aspect_ratio:"1:1","16:9","9:16","4:3","3:4","21:9","9:21"model: same identifiers asbaseModel
Provide at least one source: imageUrl, inputImageUrls, originalImageCompletionId
or originalImageCompletionIds.
Prefer the top-level baseModel. Server-side queue routing reads baseModel;
settings.model is forwarded to the worker. Setting both to the same value is safest.
Workflow
POST /image-edits- Poll
GET /image-edits/{id}every 3 s - On
status === "ready", readgeneratedImageCompletion.imageVersions.original
mode: "in" (inpainting) and mode: "out" (outpainting) are deprecated — use context.
4. Upscaling — POST /upscale
The public route is
/upscale(singular)./upscalesis the private web-app route and returns 404 here.
| Parameter | Type | Default | Notes |
|---|---|---|---|
imageId | UUID | — | A LetzAI image completion ID. |
imageUrl | string | — | Public image URL. Use instead of imageId. To upscale your own file, upload it via /user-assets and pass the returned imageUrl. |
mode | string | default | Upscaler model — see table. |
size | number | — | 2–12; output tier — see table. |
strength | number | 1 | 1–5. |
prompt | string | — | Optional guidance for creative upscalers. |
webhookUrl, organizationId |
mode | Upscaler | size → output | Credits |
|---|---|---|---|
nano-banana-pro | Google Gemini 3 Pro | 4 → 1K · 8 → 2K · 12 → 4K | 80 / 160 / 240 |
nano-banana-2 | Google Gemini 3.1 Flash | 4 → 1K · 8 → 2K · 12 → 4K | 50 / 100 / 150 |
gpt-image-2 | OpenAI GPT Image 2 | 4 → 1K · 8 → 2K · 12 → 4K | 160 / 240 / 480 |
pruna | Pruna P-Image-Upscale | 4 → 1 MP · 8 → 4 MP · 12 → 16 MP | 20 / 40 / 80 |
default | LetzAI in-house | — | 20 |
Workflow
POST /upscale- Poll
GET /upscale/{id}every 3 s - On
status === "ready", readimageVersions.original
5. Uploading Your Own Files — POST /user-assets
Two-step pre-signed S3 upload. Use this to get a public URL for a local file before
feeding it to /image-edits, /videos or /upscale.
POST /user-assetswith{ extension }(plus optionaloriginalFilename,mimeType,fileSize,caption,metadata,numberOfImages).PUTthe raw file bytes to the returneduploadUrlwith the matchingContent-Typeheader. NoAuthorizationheader — the URL is already signed.- The file is then reachable at
imageUrlfrom the step-1 response.
Allowed extension values: jpg, jpeg, png, gif, webp, mp4, webm, mov,
avi, mp3, wav, ogg, m4a, aac, flac.
POST /user-images is the older image/video-only variant of the same flow; prefer
/user-assets, which also accepts audio.
See examples/uploads_and_training.md.
6. Custom AI Models (@modelname)
Trained models for persons, objects and styles. Tag them inside any image or edit
prompt: @john_doe on the beach at sunset.
List: GET /models — query params page, limit, sortBy, sortOrder, search,
name, userId, username, class (person | object | style), type,
description, privacy (public | private | licensed), systemVersion,
isActive, status. Pagination is reported through the X-Total-Count,
X-Current-Page, X-Per-Page and X-Total-Pages response headers.
Get one: GET /models/{id}
Train a new model: POST /models — this is available over the API (Enterprise
plans).
| Parameter | Notes |
|---|---|
name | Required. Alphanumeric, _ and ., max 50 chars. Becomes the @tag. |
class | Required. person | style | object |
privacy | public | private | licensed |
type | Optional; auto-generated when omitted. |
trainingDataUrls | 1–50 public image URLs. Upload via /user-assets first. |
trainingMode | e.g. default, slow |
settings | e.g. ["NO_ADULT_CONTENT", "NO_VIOLENCE"] |
description, website, webhookUrl, organizationId | Optional. |
Training starts automatically. Poll GET /models/{id} until status is available.
Manage: PATCH /models/{id}, DELETE /models/{id},
PUT /models/{id}/thumbnail.
Workflow Decision Tree
Create an image → pick baseModel + mode from the model table → POST /images →
poll GET /images/{id} → imageVersions.original.
Use a trained model → GET /models?class=person to find the name → put
@name in the prompt → generate normally.
Edit an image → get a source (URL, /user-assets upload, or a LetzAI completion id)
→ POST /image-edits with mode: "context" → poll → generatedImageCompletion.imageVersions.original.
Create a video → optional source image → POST /videos with
settings.mode = a video-* key → poll → videoVersions.original.
Upscale → POST /upscale with imageId or imageUrl → poll → imageVersions.original.
Train a model → upload images via /user-assets → POST /models with
trainingDataUrls → poll GET /models/{id} until available.
Status Polling
Every generation endpoint is asynchronous: the POST returns an id, and you poll the
matching GET until a terminal status.
| Resource | Statuses |
|---|---|
| Images | new · generating · ready · failed · interrupted · not_allowed · hidden |
| Videos | new · generating · ready · saved · failed · interrupted |
| Image edits | new · generating · ready · saved · failed · interrupted |
| Upscales | new · generating · ready · failed |
| Models | new · pending · training · finished · available · failed |
There is no "in progress" status — in-flight jobs report generating. Treat
ready and saved as success; failed, interrupted and not_allowed as terminal
failures. Responses also carry progress (0–100) and, during generation, a base64
previewImage.
Recommended intervals: 3 s for images / edits / upscales, 2–3 s for videos. Pass a
webhookUrl instead of polling for production workloads.
For a full implementation, see examples/polling_pattern.md.
Error Handling
| Status | Meaning | Fix |
|---|---|---|
| 400 | Invalid parameters, or an unknown field in the body | Check ranges and remove fields that are not in the schema |
| 401 | Missing/invalid key, or not a member of organizationId | Check the Authorization header |
| 402 | Insufficient credits | Top up at letz.ai/subscription |
| 404 | Resource not found — or you used a private-API route | Check the id, and that the path exists on api.letz.ai |
| 429 | Rate limited | Back off exponentially |
| 500 | Server error | Retry with backoff |
Limitations
- All generation is asynchronous — poll or use webhooks.
- Videos are billed per model; per-second models can be expensive at 1080p/4K.
modevalues are model-specific; an unsupported tier falls back to the model default.- Seedance 2.0 Enterprise requires an
organizationIdyou are a member of. - A paid subscription is required for API access.
Quick Reference: API Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/images | POST | Create image |
/images | GET | List / filter images |
/images/{id} | GET | Image status + URLs |
/images/{id}/interruption | PUT | Stop generation |
/images/{id}/privacy | PUT | { privacy: "public" | "private" | "licensed" } |
/images/{id}/prompt-privacy | PUT | Hide/show the prompt publicly |
/image-edits | POST | Create edit |
/image-edits | GET | List edits |
/image-edits/{id} | GET | Edit status + URLs |
/image-edits/{imageCompletionId}/mask | GET | Mask used for a legacy inpaint |
/videos | POST | Create video |
/videos | GET | List videos |
/videos/{id} | GET | Video status + URLs |
/videos/{id}/privacy | PUT | Change video privacy |
/videos/{id}/prompt-privacy | PUT | Hide/show the prompt publicly |
/upscale | POST | Create upscale |
/upscale | GET | List upscales |
/upscale/{id} | GET | Upscale status + URLs |
/upscale/{id} | DELETE | Delete an upscale |
/models | GET | List models |
/models | POST | Train a new model |
/models/{id} | GET | Model details |
/models/{id} | PATCH | Update model metadata |
/models/{id} | DELETE | Delete model |
/models/{id}/thumbnail | PUT | Set thumbnail |
/user-assets | POST | Get a pre-signed upload URL (image/video/audio) |
/user-assets | GET | List uploads |
/user-assets/{id} | GET / PATCH / DELETE | Manage an upload |
/user-images | POST / GET | Legacy image+video-only upload flow |
/user-images/{id} | GET / DELETE | Manage a legacy upload |
/realtime/health | GET | Realtime gateway health |
Not on the public API (private web-app routes — these 404): /upscales,
/video-edits, /image_completions, PUT /videos/{id}/interruption.
Key response fields
- Images / upscales:
imageVersions.original,imageVersions["1920x1920"],imageVersions["640x640"] - Edits:
generatedImageCompletion.imageVersions.original(source inoriginalImageCompletion) - Videos:
videoVersions.original - In flight:
progress(0–100),previewImage(base64),statusDetailon failure
Model Catalogue
To see the current list of AI Models that are supported on LetzAI, including their parameters and token costs, always read the models.json file:
Model catalogue (live): letz.ai/docs/models.json
Additional Resources
- Swagger / OpenAPI: api.letz.ai/doc ·
/doc-json - Developer docs: letz.ai/docs/api
- Model catalogue (live): letz.ai/docs/models.json
- Detailed reference: api_reference.md
- Code examples: examples/
- LetzAI Documentation with all features of the platform: letz.ai/docs