PopNowDocs API
Pour commencer
Contenu principal

Démarrage rapide

Créez une clé API, envoyez votre première requête et téléchargez le résultat, en cinq minutes environ.

Cette page vous mène de zéro à une première image générée, avec une clé et une requête. Tout le reste — vidéo, audio, webhooks, envois de fichiers — c’est la même requête avec un autre model et un autre input.

Avant de commencer

  • Un compte PopNow. Inscrivez-vous sur popnow.ai. Les crédits offerts à l’inscription fonctionnent aussi avec l’API ; quand il vous en faut davantage, achetez un pack de crédits. Il n’y a pas d’offre API séparée.
  • Un terminal avec curl. Les exemples utilisent bash. Sous Windows, passez par WSL ou Git Bash.

1. Créer une clé API

Ouvrez la console API et choisissez Create key. Copiez la clé tout de suite : la valeur complète n’est affichée qu’une fois. Placez-la ensuite dans une variable d’environnement pour qu’elle n’apparaisse jamais dans votre code :

export POPNOW_API_KEY="sk-popnow-..."

Chaque clé commence par sk-popnow- et consomme les crédits de votre compte. Gardez-la côté serveur ; les restrictions, la rotation et la marche à suivre en cas de fuite sont expliquées dans Authentification.

2. Envoyer une tâche

Collez ceci dans le même terminal. La requête demande une image à un modèle rapide et coûte un ou deux crédits :

POST /api/v1/jobs/createTask?wait=60
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"
  }
}'

Le rôle de chaque partie :

  • model est l’identifiant du modèle : quel modèle tourne et pour quelle tâche. Tous les identifiants figurent dans Modèles.
  • input est validé par le schéma d’entrée propre à ce modèle. Les champs inconnus sont refusés : une faute de frappe provoque une erreur immédiate au lieu d’être ignorée en silence.
  • Idempotency-Key sécurise les nouvelles tentatives : renvoyez la même clé après un délai dépassé et vous récupérez la tâche d’origine, sans second débit. Voir Idempotence.
  • ?wait=60 garde la connexion ouverte jusqu’à 60 secondes, si bien qu’une image rapide revient dans cette même réponse.

3. Lire le résultat

Une tâche terminée ressemble à ceci :

200 · recordInfo / createTask?wait=60
{
  "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 vaut succeeded. Une tâche qui n’a pas pu aboutir indique failed avec un errorCode ; voir Erreurs.
  • output.assets[0].url est un lien signé vers le fichier. Il reste valable une vingtaine de minutes, ne demande aucune clé API, et vous en obtenez un nouveau en relisant la tâche.
  • credits indique ce que la tâche a réellement coûté, en crédits entiers (1 crédit = 0,01 $) ; cost donne le même montant sous forme de chaîne en dollars US.

Si le modèle a besoin de plus de 60 secondes — c’est le cas de tous les modèles vidéo —, la réponse est un 202 avec state: "queued" et un taskId. Interrogez la tâche jusqu’à ce qu’elle soit terminée :

curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=job_..." \
  -H "Authorization: Bearer $POPNOW_API_KEY"

Vérifiez toutes les quelques secondes, jusqu’à ce que state vaille succeeded, failed ou expired. En production, passez plutôt une callBackUrl et laissez un webhook vous prévenir.

La même requête dans votre code

JavaScript (Node.js 18+)
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);
Python (requests)
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"))

L’enveloppe de réponse

Toutes les réponses JSON ont les mêmes quatre champs :

{ "code": 200, "msg": "success", "data": { }, "request_id": "req_…" }

code est un code métier, pas un statut HTTP : 200 signifie succès, toutes les autres valeurs sont listées dans Erreurs. Basez votre logique sur code, jamais sur le texte de msg. Indiquez le request_id quand vous contactez le support.

Et ensuite

Sur cette page