Quickstart
This guide takes you from no account to a finished image in a few minutes.
Get an API key
Section titled “Get an API key”-
Sign in to the console with an email link or a Google account. Your account is created the first time you sign in.
-
Add credits. On the Billing page, top up at least $10 by card or USDT. Tasks are paid from this prepaid balance, and only when they succeed.
-
Create an API key on the API keys page and copy it straight away: the secret is shown only once. Keep it in an environment variable on your server, never in front-end code.
Terminal window export VELVET_API_KEY="vk_..."
Create a task
Section titled “Create a task”A task names a model, the model’s input, and user: your own id for the end user who asked for the image (see why it’s required). FLUX 3 Klein works best with a full scene caption rather than a short request.
The SDKs are optional. Install one with npm install @velvetapi/sdk or pip install velvetapi.
curl https://api.velvetapi.dev/v1/tasks \ -H "Authorization: Bearer $VELVET_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: quickstart-001" \ -d '{ "model": "flux-3-klein", "user": "user-123", "input": { "prompt": "A candid photograph of a woman with auburn hair reading on a sunlit balcony, soft morning light, 35mm film grain.", "width": 1024, "height": 1024 } }'import { VelvetAPI } from "@velvetapi/sdk";
const velvet = new VelvetAPI({ apiKey: process.env.VELVET_API_KEY });
const task = await velvet.tasks.create( { model: "flux-3-klein", user: "user-123", input: { prompt: "A candid photograph of a woman with auburn hair reading on a sunlit balcony, soft morning light, 35mm film grain.", width: 1024, height: 1024, }, }, { idempotencyKey: "quickstart-001" },);console.log(task.id, task.state); // "queued"import os
from velvetapi import VelvetAPI
client = VelvetAPI(api_key=os.environ["VELVET_API_KEY"])
task = client.tasks.create( model="flux-3-klein", user="user-123", input={ "prompt": "A candid photograph of a woman with auburn hair reading on a sunlit balcony, soft morning light, 35mm film grain.", "width": 1024, "height": 1024, }, idempotency_key="quickstart-001",)print(task["id"], task["state"]) # "queued"The API checks the input and the prompt, holds the price from your balance and answers 202 Accepted with the task:
{ "id": "0b9c6c2e-4d3f-4a51-9a8e-2f7d1c3b5a90", "object": "task", "model": "flux-3-klein", "state": "queued", "user": "user-123", "price_usd": 0.01, "outputs": [], "error": null, "meta": {}, "created_at": "2026-10-20T06:31:00.000Z", "started_at": null, "finished_at": null}The Idempotency-Key header makes the request safe to retry: sending it again returns the same task instead of creating and charging a second one.
Wait for the result
Section titled “Wait for the result”Poll the task every second or two until its state is succeeded, failed or cancelled. A 1024 × 1024 image takes a few seconds once a GPU is warm; after a quiet period the first task can wait longer while a worker starts.
curl https://api.velvetapi.dev/v1/tasks/0b9c6c2e-4d3f-4a51-9a8e-2f7d1c3b5a90 \ -H "Authorization: Bearer $VELVET_API_KEY"const done = await velvet.tasks.wait(task.id);if (done.state === "succeeded") console.log(done.outputs.map((output) => output.url));else console.error(done.state, done.error);done = client.tasks.wait(task["id"])if done["state"] == "succeeded": print([output["url"] for output in done["outputs"]])else: print(done["state"], done["error"])A finished task lists its images in outputs:
{ "id": "0b9c6c2e-4d3f-4a51-9a8e-2f7d1c3b5a90", "object": "task", "model": "flux-3-klein", "state": "succeeded", "user": "user-123", "price_usd": 0.01, "outputs": [ { "url": "https://cdn.velvetapi.dev/o/7d0e5b8a-2c41-4f7e-9b1a-3e6f2d8c9a10/0b9c6c2e-4d3f-4a51-9a8e-2f7d1c3b5a90/0.jpg", "content_type": "image/jpeg", "width": 1024, "height": 1024 } ], "error": null, "meta": { "seed": 1834201977, "steps": 16, "queue_ms": 850, "run_ms": 4400 }, "created_at": "2026-10-20T06:31:00.000Z", "started_at": "2026-10-20T06:31:00.850Z", "finished_at": "2026-10-20T06:31:05.400Z"}If the task failed, error says why and the hold has already gone back to your balance.
Next steps
Section titled “Next steps”- Skip polling with webhooks.
- Read the content policy and handle
prompt_blockedand other errors. - See every input of FLUX 3 Klein, including edits from reference images.