letzai-api

v2026.09.24

Generate AI images and videos via the LetzAI API. Images with Nano Banana Pro, Seedream 5, Flux 2, GPT Image 2; videos with Veo 3.1, Kling V3, Seedance 2.0. Includes context editing, upscaling, asset uploads, and custom @model training. Use for content creation apps and automation.

GitHub
Install command
npx skhub add letz-ai/letzai-api
Markdown
SKILL.md

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-json and /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.ai is the public developer API described here. https://private-api.letz.ai powers 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

ParameterTypeDefaultNotes
promptstring—Required. May contain @modelname tags.
baseModelstringaccount defaultSee model table below.
modestringmodel defaultResolution tier — allowed values differ per model.
widthint1600480–2160
heightint1600480–2160
qualityint21–6
creativityint21–6
hasWatermarkbooltrue
systemVersionintaccount default2 or 3
hideFromUserProfileboolfalse
webhookUrlstring—POSTed when the job finishes.
organizationIdUUID—Bill credits to an org you belong to.

Image models

mode is the resolution tier, and the accepted values are model-specific.

ModelbaseModelmode valuesCredits (generate)Credits (edit)
Nano Banana Pro (Google)gemini-3-pro-imagedefault (1K) · 2k (HD) · 4k80 / 160 / 24080 / 160 / 240
Nano Banana 2 (Google)nbf-inferenceshdefault (1K) · 2k (HD) · 4k40 / 80 / 16050 / 100 / 150
Nano Banana 2 Lite (Google)nano-banana-2-litedefault (1K)2025
Seedream 5 Pro (ByteDance)seedream-5-0-pro2k (HD) · 4k80 / 16080 / 160
Seedream 4.5 (ByteDance)seedream-4-5-2511282k (HD) · 4k80 / 16080 / 160
Flux 2 (Black Forest Labs)flux21k · hd60 / 12060 / 120
GPT Image 2 (OpenAI)gpt-image-21k · hd · 4k160 / 240 / 480160 / 240 / 480
WAN 2.7 Image Pro (Alibaba)wan-2-7-image-pro1k · 2k1010

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

  1. POST /images
  2. Read id from the response
  3. Poll GET /images/{id} every 3 s
  4. On status === "ready", read imageVersions.original

See examples/image_generation.js.

2. Video Generation — POST /videos

ParameterTypeNotes
promptstringRequired.
originalImageCompletionIdUUIDAnimate a previously generated LetzAI image.
imageUrlstringAnimate a public image URL.
imageUrlsstring[]Multi-frame: [0] = first frame, [1] = last frame.
promptsobject[]Multi-shot storyboards (video-kling3): [{ prompt, duration }].
baseModelstringOptional; settings.mode is the usual selector.
width / height / resolutionnumberOptional output sizing.
settingsobjectModel + duration + audio (below).
webhookUrlstring
hidePromptbool
organizationIdUUID

Image input is optional — omit all of originalImageCompletionId / imageUrl / imageUrls for pure text-to-video.

settings

FieldNotes
modeVideo model key — see table.
durationSeconds, clamped to the model's allowed values.
withSoundEnable native audio where supported.
highQualityHigher-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.

Modelsettings.modeDurationCredits
Google Veo 3.1video-veo318 s (fixed)1500 · ×2 with audio · ×2 at 1080p
Kling V3video-kling33–15 s150 · 300 with audio
Kling V2.6video-kling265 or 10 s150 · ×2 with audio · ×2 at 1080p
WAN 2.5video-wan255 or 10 s110 · ×2 at 1080p (image-to-video only)
Seedance 2.0video-seedance24–15 sper second: 105 @480p · 210 @720p · 500 @1080p · 1000 @4K (audio always on)
Seedance 2.0 Enterprisevideo-seedance2-enterprise4–15 ssame as Seedance 2.0; requires organizationId
Gemini Omni Flashvideo-gemini-omni3–10 s100 per second (audio always on)

Workflow

  1. POST /videos
  2. Poll GET /videos/{id} every 2–3 s
  3. On status === "ready", read videoVersions.original

See examples/video_generation.py.

3. Image Editing — POST /image-edits

ParameterTypeNotes
modestringRequired. context (AI editing) or skin (skin fix).
promptstringEdit instruction. May contain @modelname tags.
imageUrlstringSingle source image URL.
inputImageUrlsstring[]Multi-reference source images (up to 9 in practice).
originalImageCompletionIdUUIDEdit a previously generated LetzAI image.
originalImageCompletionIdsUUID[]Several LetzAI images as sources.
baseModelstringSame identifiers as image generation.
settingsobject{ resolution, aspect_ratio, model }
imageCompletionsCountintVariations to generate (1–5, default 1). Not used by skin.
maskstringBase64 mask, legacy inpainting only.
width / heightnumberTarget 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 as baseModel

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

  1. POST /image-edits
  2. Poll GET /image-edits/{id} every 3 s
  3. On status === "ready", read generatedImageCompletion.imageVersions.original

mode: "in" (inpainting) and mode: "out" (outpainting) are deprecated — use context.

4. Upscaling — POST /upscale

The public route is /upscale (singular). /upscales is the private web-app route and returns 404 here.

ParameterTypeDefaultNotes
imageIdUUID—A LetzAI image completion ID.
imageUrlstring—Public image URL. Use instead of imageId. To upscale your own file, upload it via /user-assets and pass the returned imageUrl.
modestringdefaultUpscaler model — see table.
sizenumber—2–12; output tier — see table.
strengthnumber11–5.
promptstring—Optional guidance for creative upscalers.
webhookUrl, organizationId
modeUpscalersize → outputCredits
nano-banana-proGoogle Gemini 3 Pro4 → 1K · 8 → 2K · 12 → 4K80 / 160 / 240
nano-banana-2Google Gemini 3.1 Flash4 → 1K · 8 → 2K · 12 → 4K50 / 100 / 150
gpt-image-2OpenAI GPT Image 24 → 1K · 8 → 2K · 12 → 4K160 / 240 / 480
prunaPruna P-Image-Upscale4 → 1 MP · 8 → 4 MP · 12 → 16 MP20 / 40 / 80
defaultLetzAI in-house—20

Workflow

  1. POST /upscale
  2. Poll GET /upscale/{id} every 3 s
  3. On status === "ready", read imageVersions.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.

  1. POST /user-assets with { extension } (plus optional originalFilename, mimeType, fileSize, caption, metadata, numberOfImages).
  2. PUT the raw file bytes to the returned uploadUrl with the matching Content-Type header. No Authorization header — the URL is already signed.
  3. The file is then reachable at imageUrl from 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).

ParameterNotes
nameRequired. Alphanumeric, _ and ., max 50 chars. Becomes the @tag.
classRequired. person | style | object
privacypublic | private | licensed
typeOptional; auto-generated when omitted.
trainingDataUrls1–50 public image URLs. Upload via /user-assets first.
trainingModee.g. default, slow
settingse.g. ["NO_ADULT_CONTENT", "NO_VIOLENCE"]
description, website, webhookUrl, organizationIdOptional.

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.

ResourceStatuses
Imagesnew · generating · ready · failed · interrupted · not_allowed · hidden
Videosnew · generating · ready · saved · failed · interrupted
Image editsnew · generating · ready · saved · failed · interrupted
Upscalesnew · generating · ready · failed
Modelsnew · 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

StatusMeaningFix
400Invalid parameters, or an unknown field in the bodyCheck ranges and remove fields that are not in the schema
401Missing/invalid key, or not a member of organizationIdCheck the Authorization header
402Insufficient creditsTop up at letz.ai/subscription
404Resource not found — or you used a private-API routeCheck the id, and that the path exists on api.letz.ai
429Rate limitedBack off exponentially
500Server errorRetry 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.
  • mode values are model-specific; an unsupported tier falls back to the model default.
  • Seedance 2.0 Enterprise requires an organizationId you are a member of.
  • A paid subscription is required for API access.

Quick Reference: API Endpoints

EndpointMethodPurpose
/imagesPOSTCreate image
/imagesGETList / filter images
/images/{id}GETImage status + URLs
/images/{id}/interruptionPUTStop generation
/images/{id}/privacyPUT{ privacy: "public" | "private" | "licensed" }
/images/{id}/prompt-privacyPUTHide/show the prompt publicly
/image-editsPOSTCreate edit
/image-editsGETList edits
/image-edits/{id}GETEdit status + URLs
/image-edits/{imageCompletionId}/maskGETMask used for a legacy inpaint
/videosPOSTCreate video
/videosGETList videos
/videos/{id}GETVideo status + URLs
/videos/{id}/privacyPUTChange video privacy
/videos/{id}/prompt-privacyPUTHide/show the prompt publicly
/upscalePOSTCreate upscale
/upscaleGETList upscales
/upscale/{id}GETUpscale status + URLs
/upscale/{id}DELETEDelete an upscale
/modelsGETList models
/modelsPOSTTrain a new model
/models/{id}GETModel details
/models/{id}PATCHUpdate model metadata
/models/{id}DELETEDelete model
/models/{id}/thumbnailPUTSet thumbnail
/user-assetsPOSTGet a pre-signed upload URL (image/video/audio)
/user-assetsGETList uploads
/user-assets/{id}GET / PATCH / DELETEManage an upload
/user-imagesPOST / GETLegacy image+video-only upload flow
/user-images/{id}GET / DELETEManage a legacy upload
/realtime/healthGETRealtime 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 in originalImageCompletion)
  • Videos: videoVersions.original
  • In flight: progress (0–100), previewImage (base64), statusDetail on 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

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

/

Default branch

main

Latest commit

6b108a4

Tree SHA

2f60032