n8n workflow for AI images and video
Generate AI images, video and audio in n8n with the built-in HTTP Request node and the PopNow API. Importable workflow JSON, credential setup, polling loop, webhooks and fixes for common errors.
n8n needs no community node to use PopNow: two built-in HTTP Request nodes, a Wait and an If are enough to create a task, wait for it and hand the file to the rest of your workflow. The same pattern works for every image, video and audio model, so you can feed a spreadsheet of prompts into a text-to-image model, turn new product photos into short videos, or voice a script line by line.
This page matches the n8n page on popnow.ai, which builds the same workflow for whichever model you pick.

What you need
- n8n 1.x (cloud or self-hosted). The HTTP Request node must be version 4 or newer.
- A PopNow API key from the API console. Give n8n its own key with a daily spend cap, so a runaway loop cannot drain your balance.
- Credits on your account. Test runs with the model below cost 2 credits each.
1. Create the credential
In n8n open Credentials → Add credential → Header Auth and fill in:
| Field | Value |
|---|---|
| Name | PopNow |
| Header name | Authorization |
| Header value | Bearer sk-popnow-… (your key, with the word Bearer and a space in front) |
To check the key before you build anything, run this in a terminal; it reads your balance and costs nothing:
curl "https://api.popnow.ai/api/v1/chat/credit" \
-H "Authorization: Bearer $POPNOW_API_KEY"2. Import the workflow
Copy the JSON, click an empty spot on the n8n canvas and paste. Then open Create task and Check task and select the PopNow credential in both.
The workflow runs: Start → Create task → Wait 5 s → Check task → Finished? If the task is still running, it loops back to the wait; when it is done, File URL outputs state, fileUrl and error.
What each node does:
| Node | Setting | Why |
|---|---|---|
| Create task | POST /api/v1/jobs/createTask, JSON body { "model", "input" } | model is any model ID from Models; input must match that model's schema |
| Create task | Header Idempotency-Key: {{ $execution.id }} | If n8n retries the node, you get the same task back instead of paying twice. See Idempotency |
| Wait 5 s | 5 seconds | Images usually finish in one or two loops; video takes one to three minutes |
| Check task | GET /api/v1/jobs/recordInfo?taskId=… | Reads the task's state and output |
| Finished? | state is final and no file is still being copied | succeeded, failed and expired are final; see Tasks |
| File URL | data.output.assets[0].url | A signed link that works for about 20 minutes. Download it in the next node if you need to keep the file |
Change the model or the input
Edit the JSON body of Create task. Every model's page lists its ID, fields and price; a few common swaps:
| Goal | model | input |
|---|---|---|
| Better text in images | google/nano-banana-2.1/text-to-image | prompt, aspect_ratio, resolution (8 credits at 1K) |
| Edit a photo | google/nano-banana-2.1/edit | prompt, image_urls |
| Photo to video | minimax/h3/image-to-video | prompt, image_url, duration_seconds (28 credits for 5 s at 768p) |
| Voiceover | google/gemini-3.8-flash-tts/text-to-speech | text, voice_id |
To use data from an earlier node, switch the body to an expression, for example:
{{ JSON.stringify({ model: 'alibaba/z-image-turbo/text-to-image', input: { prompt: $json.prompt, aspect_ratio: '16:9' } }) }}Files from earlier nodes need a public https URL or an upload first; Media shows the three upload calls, which map onto three HTTP Request nodes.
Use a webhook instead of polling
For long video jobs, let PopNow call n8n instead of looping. Add a Webhook trigger node (POST) in a second workflow, copy its production URL, and pass it as callBackUrl in the Create task body:
{
"model": "minimax/h3/image-to-video",
"input": { "image_url": "https://media.popnow.ai/movie/lighthouse.webp", "prompt": "The waves roll in slowly" },
"callBackUrl": "https://your-n8n.example.com/webhook/popnow"
}The webhook URL must be public HTTPS, so a local n8n needs a tunnel. Each delivery is signed; Webhooks shows how to check the signature in a Code node, and why you should store request_id to ignore repeat deliveries.
The same call outside n8n
Useful for testing a body before you paste it into the node.
curl -X POST "https://api.popnow.ai/api/v1/jobs/createTask?wait=60" \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"model": "alibaba/z-image-turbo/text-to-image", "input": {"prompt": "A small red fox curled up in a teacup, soft morning light, studio photo", "aspect_ratio": "1:1"}}'import os, uuid, requests
res = requests.post(
"https://api.popnow.ai/api/v1/jobs/createTask",
params={"wait": 60},
headers={"Authorization": f"Bearer {os.environ['POPNOW_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
json={"model": "alibaba/z-image-turbo/text-to-image", "input": {"prompt": "A small red fox curled up in a teacup, soft morning light, studio photo", "aspect_ratio": "1:1"}},
timeout=90,
).json()
print(res["data"]["state"], res["data"].get("output", {}).get("assets", [{}])[0].get("url"))const res = await fetch('https://api.popnow.ai/api/v1/jobs/createTask?wait=60', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POPNOW_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
model: 'alibaba/z-image-turbo/text-to-image',
input: { prompt: 'A small red fox curled up in a teacup, soft morning light, studio photo', aspect_ratio: '1:1' },
}),
});
const { data } = await res.json();
console.log(data.state, data.output?.assets?.[0]?.url);Pricing
The workflow spends credits only in Create task; reading tasks is free. A task that fails or expires costs nothing, and a retried node with the same Idempotency-Key is not charged twice. Price each model with jobs/quote before you run it at scale, and see Credits and refunds for the rules.
Common errors
| n8n shows | Why | Fix |
|---|---|---|
401 from Create task | The credential is missing, or the value lacks Bearer | Header value must be Bearer sk-popnow-… |
code: 400 with a field name in msg | A field is not in the model's schema, or a value is out of range | Check the model's page; unknown fields are rejected |
code: 40201 | Not enough credits for this task's hold | Top up, or pick a cheaper model or setting |
code: 40202 | The key's spend cap would be exceeded | Raise the cap for this key in the API console |
code: 429 | Too many requests | Lengthen the wait, or run fewer items in parallel; see Rate limits |
| The loop never ends | The task is still running, or Finished? reads the wrong field | Video can take minutes; make sure Check task reads the taskId from Create task |
fileUrl works, then returns 403 later | Signed links last about 20 minutes | Download the file in the same run, or read the task again for a fresh link |
state: failed | The model could not finish, or declined the content | Nothing was charged; read errorCode and see Errors |
Is there an official PopNow community node for n8n?
Not yet. The built-in HTTP Request node covers everything the API does, and the workflow on this page imports in one paste.
Can n8n run several generations at once?
Yes. Each item that reaches Create task becomes its own task and they render in parallel. Keep an eye on the rate limits and use a spend cap on the key.
How do I save the generated file to Google Drive or S3?
Add an HTTP Request node after File URL that downloads fileUrl as a file (response format File), then pass it to the Google Drive, S3 or any other storage node.
Related
Recipes
Batch images from a CSV, photo to video, voiceovers and notifications in Python and Node.
Webhooks
Signed callbacks, retries and duplicate handling.
ComfyUI
A custom node that runs PopNow models in your graph.
Build the workflow for any model
The n8n page on popnow.ai generates this JSON for the model you choose.

