Szybki start
Utwórz klucz API, wyślij pierwsze zapytanie i pobierz wynik — w około pięć minut.
Ta strona prowadzi od zera do pierwszego wygenerowanego obrazu: jeden klucz, jedno zapytanie. Wszystko inne — wideo, audio, webhooki, przesyłanie plików — to to samo zapytanie z innym model i innym input.
Zanim zaczniesz
- Konto PopNow. Zarejestruj się na popnow.ai. Darmowe kredyty z rejestracji działają też w API; gdy potrzebujesz więcej, kup pakiet kredytów. Osobnego planu dla API nie ma.
- Terminal z
curl. Przykłady są w bashu. Na Windowsie użyj WSL albo Git Bash.
1. Utwórz klucz API
Otwórz konsolę API i wybierz Create key. Od razu skopiuj klucz: pełna wartość pojawia się tylko raz. Potem zapisz go w zmiennej środowiskowej, żeby nigdy nie trafił do kodu:
export POPNOW_API_KEY="sk-popnow-..."Każdy klucz zaczyna się od sk-popnow- i zużywa kredyty z twojego konta. Trzymaj go wyłącznie na serwerze; ograniczenia, rotację i to, co zrobić po wycieku, opisuje strona Uwierzytelnianie.
2. Wyślij zadanie
Wklej to do tego samego terminala. Zapytanie prosi szybki model o jeden obraz i kosztuje jeden–dwa kredyty:
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"
}
}'Co robi każda część:
modelto ID modelu — który model działa i do jakiego zadania. Wszystkie ID znajdziesz w Modelach.inputjest sprawdzany schematem wejściowym tego modelu. Nieznane pola są odrzucane, więc literówka od razu kończy się błędem, zamiast zostać po cichu pominięta.Idempotency-Keysprawia, że ponowienie jest bezpieczne: wyślij ten sam klucz po przekroczeniu czasu, a dostaniesz pierwotne zadanie zamiast drugiego obciążenia. Zobacz Idempotencja.?wait=60trzyma połączenie otwarte do 60 sekund, więc szybki obraz wraca w tej samej odpowiedzi.
3. Odczytaj wynik
Ukończone zadanie wygląda tak:
{
"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_…"
}statema wartośćsucceeded. Zadanie, którego nie udało się dokończyć, mafailedierrorCode; zobacz Błędy.output.assets[0].urlto podpisany link do pliku. Działa około 20 minut, nie wymaga klucza API, a nowy dostaniesz, odczytując zadanie jeszcze raz.creditsto faktyczny koszt zadania w pełnych kredytach (1 kredyt = 0,01 USD);costpodaje tę samą kwotę jako ciąg znaków w dolarach.
Jeśli model potrzebuje więcej niż 60 sekund — a wszystkie modele wideo potrzebują — odpowiedzią jest 202 ze state: "queued" i taskId. Odpytuj zadanie, aż się zakończy:
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=job_..." \
-H "Authorization: Bearer $POPNOW_API_KEY"Sprawdzaj co kilka sekund, aż state będzie succeeded, failed albo expired. Na produkcji lepiej przekaż callBackUrl i daj się powiadomić webhookiem.
To samo zapytanie w kodzie
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"))Koperta odpowiedzi
Każda odpowiedź JSON ma te same cztery pola:
{ "code": 200, "msg": "success", "data": { }, "request_id": "req_…" }code to kod biznesowy, a nie status HTTP: 200 oznacza sukces, pozostałe wartości opisuje strona Błędy. Rozgałęziaj logikę według code, nigdy według treści msg. Kontaktując się z pomocą, podaj request_id.

