Início rápido
Crie uma chave de API, envie sua primeira requisição e baixe o resultado em uns cinco minutos.
Esta página leva você do zero à primeira imagem gerada, com uma chave e uma requisição. Todo o resto — vídeo, áudio, webhooks, uploads — é a mesma requisição com outro model e outro input.
Antes de começar
- Uma conta PopNow. Cadastre-se em popnow.ai. Os créditos grátis do cadastro também valem na API; quando precisar de mais, compre um pacote de créditos. Não existe um plano separado para a API.
- Um terminal com
curl. Os exemplos usam bash. No Windows, use WSL ou Git Bash.
1. Crie uma chave de API
Abra o console da API e escolha Create key. Copie a chave na hora: o valor completo só aparece uma vez. Depois, coloque-a numa variável de ambiente para que ela nunca vá parar no código:
export POPNOW_API_KEY="sk-popnow-..."Toda chave começa com sk-popnow- e usa os créditos da sua conta. Guarde-a só no servidor; restrições, rotação e o que fazer se ela vazar estão em Autenticação.
2. Envie uma tarefa
Cole isto no mesmo terminal. A requisição pede uma imagem a um modelo rápido e custa um ou dois créditos:
export POPNOW_API_KEY="sk-popnow-..." # your key from the API console
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"
}
}'O que cada parte faz:
modelé o ID do modelo: qual modelo roda e para qual tarefa. Todos os IDs estão em Modelos.inputé validado pelo schema de entrada daquele modelo. Campos desconhecidos são rejeitados, então um erro de digitação dá erro na hora em vez de ser ignorado em silêncio.Idempotency-Keydeixa a nova tentativa segura: reenviando a mesma chave depois de um timeout, você recebe a tarefa original em vez de uma segunda cobrança. Veja Idempotência.?wait=60mantém a conexão aberta por até 60 segundos, e uma imagem rápida volta nesta mesma resposta.
3. Leia o resultado
Uma tarefa concluída fica assim:
{
"code": 200,
"msg": "success",
"data": {
"taskId": "job_01JH8Z4Q5W2N7R3K9M6P1C0VXD",
"model": "alibaba/z-image-turbo/text-to-image",
"state": "succeeded",
"output": {
"assets": [
{
"url": "https://…signed-link…",
"expiresAt": "2026-10-16T09:20:00Z",
"mime": "image/png",
"width": 1024,
"height": 1024
}
]
},
"credits": 2,
"cost": "0.02",
"settled": true
},
"request_id": "req_…"
}stateésucceeded. Uma tarefa que não conseguiu terminar mostrafailede traz umerrorCode; veja Erros.output.assets[0].urlé um link assinado para o arquivo. Vale por uns 20 minutos, não precisa de chave de API e você sempre consegue um novo lendo a tarefa de novo.creditsé quanto a tarefa custou, em créditos inteiros (1 crédito = US$ 0,01);costtraz o mesmo valor como string em dólares.
Se o modelo precisar de mais de 60 segundos — todos os de vídeo precisam —, a resposta é um 202 com state: "queued" e um taskId. Consulte a tarefa até ela terminar:
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=job_..." \
-H "Authorization: Bearer $POPNOW_API_KEY"Confira a cada poucos segundos até state virar succeeded, failed ou expired. Em produção, prefira passar um callBackUrl e deixar um webhook avisar você.
A mesma requisição em código
const API = 'https://api.popnow.ai/api/v1';
const headers = {
Authorization: `Bearer ${process.env.POPNOW_API_KEY}`,
'Content-Type': 'application/json',
};
const created = await fetch(`${API}/jobs/createTask`, {
method: 'POST',
headers: { ...headers, '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' },
}),
}).then((r) => r.json());
if (created.code !== 200) throw new Error(`${created.code} ${created.msg}`);
// Poll until the task reaches a final state.
let task;
do {
await new Promise((r) => setTimeout(r, 3000));
const res = await fetch(`${API}/jobs/recordInfo?taskId=${created.data.taskId}`, { headers });
task = (await res.json()).data;
} while (task.state === 'queued' || task.state === 'running');
console.log(task.state, task.output?.assets?.[0]?.url);import os, time, uuid, requests
API = "https://api.popnow.ai/api/v1"
headers = {"Authorization": f"Bearer {os.environ['POPNOW_API_KEY']}"}
created = requests.post(
f"{API}/jobs/createTask",
headers={**headers, "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"},
},
timeout=30,
).json()
if created["code"] != 200:
raise RuntimeError(f'{created["code"]} {created["msg"]}')
# Poll until the task reaches a final state.
while True:
time.sleep(3)
task = requests.get(
f"{API}/jobs/recordInfo",
headers=headers,
params={"taskId": created["data"]["taskId"]},
timeout=30,
).json()["data"]
if task["state"] not in ("queued", "running"):
break
print(task["state"], task.get("output", {}).get("assets", [{}])[0].get("url"))O envelope de resposta
Toda resposta JSON tem os mesmos quatro campos:
{ "code": 200, "msg": "success", "data": { }, "request_id": "req_…" }code é um código de negócio, não um status HTTP: 200 significa sucesso e o resto está em Erros. Decida pelo code, nunca pelo texto de msg. Informe o request_id ao falar com o suporte.

