GET/api/v1/models
All models you can use. Filter with ?category=<id>.
- Returns
{ models: Model[], count }
Create photos and videos with every model on Yumeforge from your own app, script or server. One key, plain JSON, and the same credits you use in the studio.
The API is a small REST API at https://yumeforge.com/api/v1. Requests and replies are JSON (uploads use multipart). Generation is asynchronous: you start a job, then poll it until it is completed or failed. Results are links to files we store for you.
GET /models and read its options.POST /generate.GET /jobs/{id} every few seconds and download the outputs.Jobs you start through the API also appear in your library in the studio. The API can be called from any origin (CORS is open), but it never uses your login cookie: every request needs a key.
Create a key on your API keys page. Keys start with yf_live_ and are shown only once, so store the key right away. Send it in the Authorization header of every request:
Authorization: Bearer yf_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx401.Save your key in an environment variable, then start a job. This example uses FLUX Schnell, a fast text-to-image model (from 2 credits per image).
export YF_API_KEY="yf_live_..."curl -X POST https://yumeforge.com/api/v1/generate \
-H "Authorization: Bearer $YF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "studio/flux-schnell",
"input": { "prompt": "A lighthouse at dusk, film photo", "size": "1024*1024" }
}'The reply contains the job id and the credits reserved for it:
{ "id": "5f1c2e1a-8d4b-4a53-9a55-0c8f3d2b7e10", "status": "processing", "credits": 2 }Poll the job every 2 to 5 seconds until the status is completed or failed:
curl https://yumeforge.com/api/v1/jobs/JOB_ID \
-H "Authorization: Bearer $YF_API_KEY"{
"job": {
"id": "5f1c2e1a-8d4b-4a53-9a55-0c8f3d2b7e10",
"status": "completed",
"model": "studio/flux-schnell",
"modelLabel": "FLUX Schnell",
"output": "image",
"outputs": ["https://yumeforge.com/api/media/…/result.jpg"],
"text": null,
"error": null,
"credits": 2,
"createdAt": "2026-09-30T10:00:00.000Z",
"completedAt": "2026-09-30T10:00:04.000Z"
}
}The same flow, generate and then poll, in two languages.
// Node 18+ or any modern runtime with fetch. Keep the key on your server.
const API = "https://yumeforge.com/api/v1";
const headers = {
Authorization: `Bearer ${process.env.YF_API_KEY}`,
"Content-Type": "application/json",
};
async function call(path, init = {}) {
const res = await fetch(API + path, { ...init, headers });
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
return data;
}
const job = await call("/generate", {
method: "POST",
body: JSON.stringify({
model: "studio/flux-schnell",
input: { prompt: "A lighthouse at dusk, film photo" },
}),
});
let result;
do {
await new Promise((r) => setTimeout(r, 3000));
({ job: result } = await call(`/jobs/${job.id}`));
} while (result.status === "queued" || result.status === "processing");
if (result.status === "completed") console.log(result.outputs);
else console.error(result.error);# pip install requests
import os, time, requests
API = "https://yumeforge.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['YF_API_KEY']}"}
def call(method, path, **kwargs):
res = requests.request(method, API + path, headers=HEADERS, timeout=60, **kwargs)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
return data
job = call("POST", "/generate", json={
"model": "studio/flux-schnell",
"input": {"prompt": "A lighthouse at dusk, film photo"},
})
while True:
time.sleep(3)
result = call("GET", f"/jobs/{job['id']}")["job"]
if result["status"] not in ("queued", "processing"):
break
print(result["outputs"] if result["status"] == "completed" else result["error"])All paths are relative to https://yumeforge.com. Every request needs the Authorization header.
GET/api/v1/models
All models you can use. Filter with ?category=<id>.
{ models: Model[], count }GET/api/v1/models/{id}
One model with its options. The id contains slashes, use it as is.
{ model: Model }POST/api/v1/generate
Start a generation. Credits are reserved right away and returned if it fails.
{ model, input }{ id, status, credits }GET/api/v1/jobs/{id}
Status and results of one of your jobs. Poll every 2 to 5 seconds.
{ job: Job }GET/api/v1/balance
Your credit balance.
{ credits }POST/api/v1/uploads
Upload a picture, video or audio file to use as input (multipart, field "file").
multipart/form-data{ id, url, kind, name }params lists every option the model accepts, with its type, allowed values (enum), default, range and whether it is required. Options with media take a file URL. Categories: image, edit, video, video-edit, avatar, motion, upscale, 3d, analyze, train.
{
"id": "studio/flux-schnell",
"label": "FLUX Schnell",
"brand": "FLUX",
"category": "image",
"output": "image",
"consentRequired": false,
"fromCredits": 2,
"price": "from 2 credits",
"params": [
{ "name": "prompt", "type": "string", "required": true, "description": "The positive prompt for the generation." },
{ "name": "num_images", "type": "integer", "default": 1, "minimum": 1, "maximum": 4, "required": false, "description": "…" }
]
}status is queued, processing, completed or failed. outputs holds absolute links to the result files; models that answer in text put it in text. When a job fails, error says why and the credits go back to your balance.
Put the model options in input, using the names from params. Unknown options are ignored, numbers are kept inside their range and enum values are checked.
Files. For options that take a picture, video or audio file, pass a public https URL. If the file is on your computer, upload it first with POST /api/v1/uploads (up to 50 MB) and pass the url from the reply. For bigger files, host them yourself and pass that link.
curl -X POST https://yumeforge.com/api/v1/uploads \
-H "Authorization: Bearer $YF_API_KEY" \
-F "file=@portrait.jpg"Consent. Models that work on a real person (face swap, avatars, lip sync, training on a face and similar) have consentRequired: true. For those, add "_consent": true to input. By sending it you confirm that you have permission from everyone shown and that none of them is a public figure. Without it the request fails with 400. The confirmation is stored with the job.
Errors use normal HTTP status codes and always have the same shape. Show message to people; use code in your code.
{
"error": {
"message": "This generation costs 40 credits. Top up to continue.",
"code": "insufficient_credits"
}
}| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | The body or an option is wrong, or consent is missing. The message says what to fix. |
| 401 | unauthorized | No key, a malformed key, or a revoked key. |
| 402 | insufficient_credits | Not enough credits for this generation. Top up and try again. |
| 403 | forbidden | The account is suspended, the terms are not accepted yet, or content was refused. |
| 404 | not_found | Unknown model or job, or a job that is not yours. |
| 413 | file_too_large | Uploads through the API can be up to 50 MB. |
| 415 | unsupported_file_type | Use an image, video, audio file or ZIP. |
| 422 | content_blocked | The prompt or an uploaded picture breaks the content rules. |
| 429 | rate_limited | Too many requests or running generations. Wait for the Retry-After header (seconds). |
| 502 | generation_failed | The model could not start. Your credits were returned. |
| 503 | unavailable | Maintenance or full capacity. Try again in a few minutes. |
Over a limit you get 429 with a Retry-After header in seconds. Wait that long before trying again, and poll jobs no more often than every 2 seconds.
The API uses the credits on your account, at the same prices as the studio (1 credit is €0.01 of generation). The price depends on the model and the options, like resolution, length and number of results. fromCredits on each model is the price with default options; the reply of POST /generate shows what was actually reserved.
Credits are taken when a job starts and returned automatically when it fails. Check your balance with GET /api/v1/balance and top up on the pricing page.
Everything made through the API follows the same rules as the studio. Prompts, uploaded pictures and results are checked automatically, and repeated violations can suspend the account and its keys. Read the acceptable use policy before you build, and make sure the people using your app follow it too.