API Documentation
Generate AI images and videos with the Genova Platform. Use the REST API, WebSocket for real-time updates, or our browser extensions for automated generation.
7 Models
Image & Video
~30s
Image Generation
~3min
Video (Fast)
REST + WS
Real-time Updates
Quick Start
Get Your API Key
Sign up and create an API key from Dashboard → API Keys. Your key starts with af_ and is shown only once.
Create a Generation Job
curl -X POST https://autoflow-api.aboessa101.workers.dev/api/jobs \
-H "X-API-Key: af_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"type": "image",
"prompt": "A cat playing piano in a jazz club",
"model": "imagen4",
"aspectRatio": "landscape",
"count": 1
}'{
"success": true,
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"queuePosition": 1,
"estimatedTime": 30
}Check Status & Download
# Poll status
curl https://autoflow-api.aboessa101.workers.dev/api/jobs/JOB_ID \
-H "X-API-Key: af_your_api_key_here"
# Download when completed
curl https://autoflow-api.aboessa101.workers.dev/api/jobs/JOB_ID/download \
-H "X-API-Key: af_your_api_key_here"Authentication
All API requests require authentication. Two methods are supported:
API Key
Send in the X-API-Key header.
JWT Bearer Token
Send in the Authorization: Bearer <token> header.
# API Key (recommended for server-to-server)
curl -H "X-API-Key: af_your_api_key_here" ...
# JWT Token (used by web dashboard and extensions)
curl -H "Authorization: Bearer eyJhbGciOi..." ...Available Models
Genova supports 7 AI models across two platforms: Google Flow (images & videos) and Freepik Pikaso (images).
Image Models
imagen4Imagen 4Google’s latest image generation model. Best overall quality and prompt adherence. Supports reference images.
nano_banana_proNano Banana ProFast community model optimized for artistic styles. Good for creative/stylized outputs.
nano_banana2Nano Banana 2Updated community model with improved realism. Good for photo-realistic generations.
Video Models
veo3_fastVEO 3 FastGoogle’s VEO 3 in fast mode. Generates high-quality videos with good prompt adherence in under 3 minutes.
veo3_qualityVEO 3 QualityVEO 3 at maximum quality. Slower but produces cinema-grade video output with superior detail.
veo2_fastVEO 2 FastPrevious generation VEO model. Fastest video generation, ideal for drafts and rapid iteration.
Freepik Model
freepikFreepik Pikaso AIFreepik's Pikaso AI image generator. Supports 7 aspect ratios, 2 resolutions, up to 4 images per generation, and 6 reference image modes for style-guided generation.
Freepik-specific settings:
resolution — "1K" or "2K"referenceImages.mode — see Reference ImagesDimensions & Aspect Ratios
Google Flow Models
(imagen4, nano_banana_pro, nano_banana2, veo3_*, veo2_*)| Value | Ratio | Best For |
|---|---|---|
landscape | 16:9 | Desktop wallpapers, YouTube thumbnails, presentations |
portrait | 9:16 | Mobile wallpapers, Instagram stories, TikTok |
square | 1:1 | Social media posts, profile pictures, thumbnails |
Pass as aspectRatio in the job settings.
Freepik Model
(model: "freepik")| Value | Description | Best For |
|---|---|---|
1:1 | Square | Social media, icons |
4:3 | Standard | Presentations, blog images |
3:4 | Portrait | Posters, book covers |
16:9 | Widescreen | Desktop backgrounds, banners |
9:16 | Tall / Stories | Phone wallpapers, stories |
3:2 | Photo landscape | Photography-style images |
2:3 | Photo portrait | Portrait photography |
Resolution Options
1KStandard resolution (default)2KHigh quality, larger file sizeReference Images
Upload reference images to guide the AI generation. Images should be sent as base64-encoded strings. The API normalizes them automatically.
Request Format
{
"type": "image",
"prompt": "A sunset over mountains",
"model": "imagen4",
"referenceImages": {
"mode": "ingredients",
"images": [
{
"name": "reference_1.jpg",
"data": "data:image/jpeg;base64,/9j/4AAQSkZ...",
"mimeType": "image/jpeg"
}
]
}
}The object form above is preferred. A bare string ("data:image/...;base64,..." or plain base64) is still accepted and gets an auto-generated name.
Size limit: 32MB total across all reference images in one request. Larger payloads are rejected with 413 plus receivedBytes, before any credit is spent. Resizing to 1024px on the longest edge keeps a photo well under 1MB.
Prompt limit: 500 characters. Longer prompts are rejected with 400 and receivedChars.
Stored outside the job row. Images are written to object storage and the job keeps only a pointer, so large payloads no longer fail the insert. Fetch them back with GET /api/jobs/:id/references.
Deleted with the job. Removing a job also removes its stored reference images.
Failed jobs are refunded. A job that ends in failed returns its credit automatically, including worker-side capture failures.
Consistent Characters (tag mode)
Keep the same cast across many scenes — for cartoons, storyboards and series.
First build the character inside Flow (Characters tab — image plus optional voice). Then reference it from a prompt with @name. The extension opens Flow's asset picker, selects that character and presses Add to Prompt, so the asset becomes a real prompt chip — exactly what you get by hand. The same asset is reused in every scene, which is what keeps the character consistent.
{
"type": "image",
"prompt": "@\"test Character\" man in home",
"model": "nano_banana2",
"referenceImages": {
"mode": "tag",
"characters": ["test Character"]
}
}The asset must already exist in Flow. Only the name is needed — pass characters: ["test Character"]. No image upload is involved, so a character built in Flow (with its voice) is referenced as-is.
Quote names that contain spaces. A bare @test Character stops at the space and resolves to test. Write @"test Character" or @[test Character] instead.
Names are matched on the picker row label (trimmed, case-insensitive) and must be unique. There is no "closest match" fallback — a name that does not resolve is reported rather than silently swapped for another character.
@me is your avatar. It resolves against Flow's Avatar tab and needs no entry in characters.
Validated up front. A mention with no matching character is rejected with 400 plus the missing names, so a scene never renders silently without its cast.
Works for video too. Send "type": "video" with the same tag payload to animate the same cast.
Building a Full Cartoon
Build the cast once in Flow, then submit one job per scene reusing the same characters array — every scene resolves to the same assets.
// Names must match the assets already in your Flow project.
const characters = ['sara girl', 'ahmed boy', 'magic forest'];
// Quote any name that contains a space.
const scenes = [
'@"sara girl" walks into @"magic forest" at sunrise',
'@"sara girl" and @"ahmed boy" find a glowing lantern',
'@"ahmed boy" holds the lantern high, @"magic forest" lights up',
];
for (const prompt of scenes) {
const res = await fetch('https://autoflow-api.aboessa101.workers.dev/api/jobs', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'image', // or 'video'
prompt,
model: 'nano_banana2',
aspectRatio: 'landscape',
referenceImages: { mode: 'tag', characters },
}),
});
const { jobId } = await res.json();
console.log('queued scene:', jobId);
}Scenes are queued in order and processed one at a time by the extension worker. Track progress over the WebSocket, or poll GET /api/jobs.
Reference Modes
| Mode | Platform | Description |
|---|---|---|
ingredients | Flow | Combines elements from your reference images into the generated image |
frames | Flow | Video only. Start / End keyframes (slot 0 = Start, slot 1 = End) |
tag | Flow | Named characters referenced inline as @name in the prompt. Keeps a cast consistent across scenes |
style | Freepik | Applies the artistic style of the reference to the generation |
character | Freepik | Uses a character/person from the reference in the output |
element | Freepik | Incorporates specific visual elements from the reference |
color | Freepik | Matches the color palette of the reference image |
effects | Freepik | Applies visual effects (lighting, texture) from the reference |
camera | Freepik | Matches the camera angle and perspective of the reference |
Image Tools
Optimize, inspect and cut out images without creating a generation job. Backed by Cloudflare Images — the free tier covers 5,000 unique transformations per calendar month, and repeat requests for the same image and parameters inside a month are not re-billed.
/api/images/optimizeShrink an image{
"image": "data:image/png;base64,iVBORw0KGgo...",
"width": 1024,
"format": "image/webp",
"quality": 85
}Only image is required. Defaults are width: 1024, format: image/webp, quality: 85. Allowed formats: image/webp, image/avif, image/jpeg, image/png.
Response
{
"success": true,
"image": "data:image/webp;base64,UklGRg...",
"optimized": true,
"originalBytes": 915444,
"optimizedBytes": 172774,
"savedBytes": 742670,
"savedPercent": 81
}Never returns a larger image. If re-encoding would grow the file, the original is returned with optimized: false.
Input limit: 20MB. Larger inputs are rejected with 413; an image that cannot be processed returns 422.
/api/images/infoRead metadata// request
{ "image": "data:image/png;base64,iVBORw0KGgo..." }
// response
{
"success": true,
"info": { "fileSize": 915443, "width": 1600, "height": 1200, "format": "image/png" }
}Metadata reads are not billed as transformations.
/api/images/remove-backgroundCut out a subjectYou must supply the mask. Cloudflare has no segmentation model, so this endpoint composites a mask you generate — it does not detect the subject for you. Generating the mask is free and runs locally (see below).
{
"image": "data:image/png;base64,iVBORw0KGgo...",
"mask": "data:image/png;base64,iVBORw0KGgo..."
}The mask must match the image dimensions: opaque where the subject is, transparent elsewhere. Output is always PNG so the cutout keeps its alpha channel.
Generating the mask for free
Run a segmentation model client-side with @huggingface/transformers (Apache-2.0). No server cost and the image never leaves the device until you send it.
import { pipeline } from '@huggingface/transformers';
// Runs in the browser / extension via WebGPU or WASM.
const segmenter = await pipeline('background-removal', 'briaai/RMBG-1.4');
const [{ mask }] = await segmenter(imageUrl);
// Send the mask alongside the original image.
const res = await fetch('https://autoflow-api.aboessa101.workers.dev/api/images/remove-background', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ image: originalDataUrl, mask: maskDataUrl }),
});
const { image } = await res.json(); // PNG cutout with transparencyAvoid @imgly/background-removal in a commercial product: it is AGPL-3.0, which requires publishing your source when users interact with a modified version over a network.
Optimize while creating a job
Add optimizeImage to a job request to shrink every reference image before it is stored. This runs before the size check, so it can bring an oversized set of photos under the limit instead of being rejected.
{
"type": "image",
"prompt": "a cozy reading nook",
"model": "nano_banana2",
"optimizeImage": true,
"referenceImages": {
"mode": "ingredients",
"images": [{ "name": "room.jpg", "data": "data:image/jpeg;base64,..." }]
}
}Pass an object for control: "optimizeImage": { "width": 768, "format": "image/webp", "quality": 80 }. Optimization is best-effort — if a transform fails the original image is used and the job still runs.
API Reference
Base URL: https://autoflow-api.aboessa101.workers.dev
/api/jobsCreate Generation JobCreates a new image or video generation job. Deducts 1 credit.
| Parameter | Type | Req | Description |
|---|---|---|---|
type | string | Yes | "image" or "video" |
prompt | string | Yes | Text description (max 500 chars) |
model | string | No | See Available Models. Default: "imagen4" |
aspectRatio | string | No | Flow: "landscape" / "portrait" / "square". Freepik: "1:1" / "4:3" / "3:4" / "16:9" / "9:16" / "3:2" / "2:3". Default: "landscape" |
count | number | No | Number of items (1-4). Videos always 1. Default: 1 |
quality | string | No | Freepik only: "1K" or "2K". Default: "1K" |
referenceImages | object | No | { images: string[], mode: string }. See Reference Images section |
priority | number | No | Queue priority (higher = sooner). Default: 0 |
Examples:
// Image with Imagen 4
{
"type": "image",
"prompt": "A futuristic cityscape at sunset",
"model": "imagen4",
"aspectRatio": "landscape",
"count": 2
}
// Video with VEO 3
{
"type": "video",
"prompt": "A drone flyover of a coral reef",
"model": "veo3_fast",
"aspectRatio": "landscape"
}
// Freepik with reference image
{
"type": "image",
"prompt": "A portrait in this style",
"model": "freepik",
"aspectRatio": "1:1",
"count": 4,
"quality": "2K",
"referenceImages": {
"images": ["data:image/jpeg;base64,..."],
"mode": "style"
}
}/api/jobs/:idGet Job StatusRetrieve the full details and current status of a generation job.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "image",
"status": "completed",
"prompt": "A cat playing piano in a jazz club",
"settings": {
"model": "imagen4",
"aspectRatio": "landscape",
"count": 1
},
"result_url": "generated/user-id/job-id/result.png",
"result_urls": null,
"created_at": "2025-04-02T10:30:00Z",
"started_at": "2025-04-02T10:30:02Z",
"completed_at": "2025-04-02T10:30:32Z",
"processing_time": 30,
"file_size": 1048576
}/api/jobsList JobsList your generation jobs with optional filtering and pagination.
| Query Param | Type | Description |
|---|---|---|
status | string | Filter: "pending", "queued", "processing", "completed", "failed" |
limit | number | Max results per page (default: 50) |
offset | number | Pagination offset (default: 0) |
{
"jobs": [
{ "id": "...", "type": "image", "status": "completed", "prompt": "...", ... },
{ "id": "...", "type": "video", "status": "processing", "prompt": "...", ... }
],
"total": 42
}/api/jobs/:id/downloadDownload ResultGet a signed download URL for a completed job. Redirects to the file. Only works for jobs with status completed.
curl -L https://autoflow-api.aboessa101.workers.dev/api/jobs/JOB_ID/download \
-H "X-API-Key: af_your_api_key_here" \
-o result.png/api/jobs/:idCancel JobCancel a pending or queued job. Credits are refunded if the job hasn't started processing. Returns { "success": true }.
API Key Management
/api/keysCreate a new API key. Body: { "name": "My Key" }. Returns the full key (shown only once).
/api/keysList all active (non-revoked) API keys with prefix and metadata.
/api/keys/:idPermanently revoke an API key. Cannot be undone.
User & Statistics
/api/user/meGet your profile: id, email, name, subscription plan/status, credits remaining/used.
/api/user/meUpdate profile: { "name": "New Name" }
/api/user/statsGeneration statistics: total/completed/failed/active jobs, image/video counts, credits remaining.
WebSocket (Real-time Updates)
Connect via WebSocket to receive real-time job status updates instead of polling. The dashboard and extensions both use this for instant notifications.
User Connection (Dashboard)
const ws = new WebSocket(
'wss://autoflow-api.aboessa101.workers.dev/ws/user?userId=YOUR_USER_ID'
);
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg.type, msg);
// msg.type can be:
// "welcome" — connection confirmed
// "job_started" — extension picked up your job
// "job_progress" — progress update with percentage
// "job_completed" — job done, includes resultUrl
// "job_failed" — job failed, includes error message
};Message Types
| Type | Direction | Fields |
|---|---|---|
welcome | Server → Client | { type, userId } |
job_started | Server → Client | { type, jobId } |
job_progress | Server → Client | { type, jobId, progress, message } |
job_completed | Server → Client | { type, jobId, resultUrl, resultUrls } |
job_failed | Server → Client | { type, jobId, error } |
ping | Client → Server | { type: "ping" } — keep-alive |
pong | Server → Client | { type: "pong" } — heartbeat reply |
Extension Connection
Browser extensions connect to a separate endpoint and receive job assignments:
// Extension WebSocket (used internally by Flow/Freepik extensions)
const ws = new WebSocket(
'wss://autoflow-api.aboessa101.workers.dev/ws/extension' +
'?userId=USER_ID&token=JWT_TOKEN&extensionType=flow'
// extensionType: "flow" or "freepik"
);
// Extension receives: new_job (assigned work)
// Extension sends: job_progress, job_completed, job_failed, request_jobJob Lifecycle
error_message for details. Jobs queued for 30+ minutes without assignment are auto-failed.Rate Limits
| Plan | Requests/min | Concurrent Jobs | Monthly Credits |
|---|---|---|---|
| Free | 10 | 2 | 50 |
| Starter | 60 | 5 | 500 |
| Pro | 100 | 10 | 2,000 |
| Business | 300 | 25 | 10,000 |
When rate limited, the API returns 429 Too Many Requests with a Retry-After header.
Error Codes
| Code | Description | Resolution |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource created successfully (job, API key) |
400 | Bad Request | Check required parameters: type, prompt are required |
401 | Unauthorized | Verify your API key or JWT token is valid and not expired |
402 | Payment Required | Insufficient credits. Upgrade your plan or purchase more credits |
403 | Forbidden | You don't have permission for this resource |
404 | Not Found | Job or resource doesn't exist. Check the ID |
429 | Rate Limited | Wait and retry. Check Retry-After header |
500 | Server Error | Internal error — retry the request |
Error Response Format
{
"error": "Missing required fields",
"details": "prompt is required"
}Browser Extensions
Genova uses Chrome extensions as generation workers. Each extension connects to the platform via WebSocket, receives job assignments, and uploads results automatically.
Flow Image Automator
Handles all Google Flow models (Imagen 4, Nano Banana, VEO 2/3). Captures generated media from the Flow interface and uploads to R2.
Models: imagen4, nano_banana_pro, nano_banana2, veo3_fast, veo3_quality, veo2_fast
Platform: flow.google.com
Genova Images (Freepik)
Handles Freepik Pikaso AI model. Supports 6 reference image modes, 7 aspect ratios, and 2 resolution options.
Model: freepik
Platform: freepik.com/pikaso
How it works: When you create a job via the API or dashboard, the Job Manager routes it to the correct extension type based on the model. Jobs with model: "freepik" go to the Freepik extension; all others go to Flow. The extension generates the content in the background, uploads the result to cloud storage, and reports completion.