Windpaint
Get started

Quickstart

Get access, create an API key, generate an image, and animate it into a 5 second video.

This takes you from a new account to a generated image and a short clip made from it. Each step shows the raw HTTP call with curl and the same thing with the windpaint CLI, which handles waiting and downloading for you. The whole page costs about 4.1 credits, well inside the free credits you get on approval.

Prerequisites

  • An email address, or a Google or GitHub account.
  • curl and jq for the HTTP examples.
  • Optionally, the windpaint CLI.

Request access

Sign up at app.windpaint.ai with email and password, Google, or GitHub. If you use email, confirm your address from the link we send.

Windpaint is in early access, so new accounts go on a waitlist. When your account is approved you can sign in, and your organization receives 200 free credits that expire after 30 days. That’s enough for about 2,500 images or 50 video clips. See Pricing for what things cost.

Signing up creates an organization for you with one project called Default. Everything you generate below lands in that project.

Create an API key

In the dashboard, open Settings → API Keys and create a key. Give it a name and an expiry (30, 90, 180, or 365 days). The key starts with aak_ and is shown in full only once, so copy it now and export it:

export WINDPAINT_API_KEY="aak_..."

Anyone holding the key can spend your organization’s credits. See API keys for roles, rotation, and revocation.

If you’re using the CLI, it reads WINDPAINT_API_KEY directly. To save the key instead, run:

windpaint auth login --api-key "$WINDPAINT_API_KEY"
windpaint auth whoami

Generate an image

Submit a job to the image.generate capability. Without a model, Windpaint uses the capability’s default (z-image-turbo today). The image is 16:9 here so it can be the first frame of a 16:9 clip in the next step.

curl
curl https://api.windpaint.ai/v1/generation/capabilities/image.generate \
  -H "Authorization: Bearer $WINDPAINT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "a lighthouse on a cliff at dusk, waves below, film grain",
    "aspect_ratio": "16:9"
  }'

The API answers 202 right away. Generation is asynchronous, so you get a request id and a URL to poll, not the image:

{
  "status": "queued",
  "request_id": "0b6f3a52-6a0e-4c63-9a52-2f0c1d7e9b11",
  "status_url": "https://api.windpaint.ai/v1/generation/requests/0b6f3a52-6a0e-4c63-9a52-2f0c1d7e9b11/status",
  "cancel_url": "https://api.windpaint.ai/v1/generation/requests/0b6f3a52-6a0e-4c63-9a52-2f0c1d7e9b11/cancel",
  "credits_estimate": "0.08"
}

The credits_estimate is held from your balance now and charged only if the job completes. The CLI does the polling and the download for you, so if you used it you can skip to the next step.

Wait for it and download

Poll status_url until status is one of completed, failed, nsfw, or canceled. Images usually take a few seconds; start polling after a second or two.

curl https://api.windpaint.ai/v1/generation/requests/0b6f3a52-6a0e-4c63-9a52-2f0c1d7e9b11/status \
  -H "Authorization: Bearer $WINDPAINT_API_KEY"
{
  "status": "completed",
  "request_id": "0b6f3a52-6a0e-4c63-9a52-2f0c1d7e9b11",
  "capability": "image.generate",
  "model": "z-image-turbo",
  "project_id": "5b0c8f4e-2d1a-4f7b-9c3e-8a6d2e1f0b44",
  "source": "api",
  "outputs": [
    {
      "id": "d77a2c19-4e8b-4a51-b0f3-6c2e9a1d5f08",
      "url": "https://api.windpaint.ai/v1/generation/assets/d77a2c19-4e8b-4a51-b0f3-6c2e9a1d5f08/content",
      "content_type": "image/png",
      "width": 1024,
      "height": 576
    }
  ],
  "images": [ ... ],
  "video": null,
  "credits": { "estimate": "0.08", "actual": "0.08" },
  "error": null,
  "created_at": "2026-10-04T14:02:11.204Z",
  "finished_at": "2026-10-04T14:02:15.871Z"
}

Each output is an asset. Its url needs your API key and redirects to a short-lived signed download link, so use curl -L:

curl -L https://api.windpaint.ai/v1/generation/assets/d77a2c19-4e8b-4a51-b0f3-6c2e9a1d5f08/content \
  -H "Authorization: Bearer $WINDPAINT_API_KEY" \
  -o lighthouse.png

Keep the asset id. You’ll pass it to the video job next.

If the status is failed or nsfw: the hold is released and you’re not charged. Read error, adjust the prompt, and submit again.

Animate it into a video

video.generate turns a still into a 5 second clip. Its default model (wan-2.2-i2v) needs exactly one start_frame, which can be the asset id from the previous step. You don’t need to download and re-upload anything.

curl
curl https://api.windpaint.ai/v1/generation/capabilities/video.generate \
  -H "Authorization: Bearer $WINDPAINT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "waves crash below, the lighthouse beam sweeps slowly across the sky",
    "inputs": { "start_frame": ["d77a2c19-4e8b-4a51-b0f3-6c2e9a1d5f08"] }
  }'

The clip is 480p, 5 seconds, MP4, and costs 4 credits. Video jobs take a few minutes, so poll less often: start at a couple of seconds and back off to around 15 seconds between checks. When it completes, the clip is in video and outputs; download it the same way:

curl -L "$(curl -s https://api.windpaint.ai/v1/generation/requests/<request_id>/status \
    -H "Authorization: Bearer $WINDPAINT_API_KEY" | jq -r '.video.url')" \
  -H "Authorization: Bearer $WINDPAINT_API_KEY" \
  -o lighthouse.mp4

The CLI also takes a local file for start_frame (-i start_frame=./photo.jpg) and uploads it first.

You’ve now spent 4.08 credits. Both the image and the clip are in your project’s assets, in the dashboard under Assets and at GET /v1/generation/assets.

The API has no idempotency keys. If a submit times out and you retry it, you may create and pay for a second job. Check GET /v1/generation/requests for the first one before you resubmit.

Next steps