API-Doku

Schnellstart

Von null zum ersten erzeugten Bild in drei Schritten.

Schritt 1 – Schlüssel anlegen

Öffne „Konto → API-Plattform“ und klicke oben rechts auf „Schlüssel erstellen“. Gib ihm einen Namen, den du später wiedererkennst. Der Schlüssel landet direkt nach dem Anlegen in der Zwischenablage und lässt sich danach jederzeit erneut aus der Liste kopieren.

Ein Schlüssel ist dein Konto — er gibt deine Credits aus. Du kannst ihn jederzeit erneut aus der Liste kopieren, also verteile keine Kopien: jede zusätzliche Kopie vergrößert die Angriffsfläche.

Schritt 2 – Verfügbare Modelle ansehen

Leg den Schlüssel in eine Umgebungsvariable und liste die Modelle. Die id aus der Antwort ist genau das, was du später als model übergibst.

bash
curl https://open.pikpikgo.com/v1/models \
  -H "Authorization: Bearer $PIKPIK_API_KEY"

Schritt 3 – Ein Bild erzeugen

bash
curl https://open.pikpikgo.com/v1/images/generations \
  -H "Authorization: Bearer $PIKPIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen",
    "size": "16:9",
    "quality": "2k",
    "n": 1
  }'

Standardmäßig synchron: Der Aufruf wartet, bis das Bild fertig ist, und data[0].url enthält es bereits – ein Auftragsabruf entfällt. Ein Bild braucht meist über 30 Sekunden, setze das Client-Timeout also auf 300 Sekunden.

json
{
  "created": 1786000246,
  "data": [
    { "url": "https://cdn.pikpikgo.com/ai/xxxx.png", "revised_prompt": "eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen" }
  ],
  "id": "2608101909450810293847",
  "object": "image.generation",
  "model": "img-std-1",
  "status": "succeeded",
  "n": 1,
  "credits": 10,
  "tasks": [
    {
      "id": "2608101909450810293847",
      "status": "succeeded",
      "data": [{ "url": "https://cdn.pikpikgo.com/ai/xxxx.png", "revised_prompt": "eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen" }]
    }
  ]
}

Schritt 4 – Lieber nicht warten? Asynchron

Mit async: true kehrt der Aufruf sofort zurück: status ist queued und data noch leer – gerendert wurde bisher nichts. Merke dir tasks[0].id.

bash
curl https://open.pikpikgo.com/v1/images/generations \
  -H "Authorization: Bearer $PIKPIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen",
    "size": "16:9",
    "quality": "2k",
    "n": 1,
    "async": true
  }'
json
{
  "id": "2608101909450810293847",
  "object": "image.generation",
  "created": 1786000185,
  "model": "img-std-1",
  "status": "queued",
  "n": 1,
  "credits": 10,
  "tasks": [
    { "id": "2608101909450810293847", "status": "queued", "data": [] }
  ],
  "data": []
}

Diese id pollen: Sobald status auf succeeded steht, enthält data[0].url das Bild. Videos funktionieren ausschließlich so.

bash
curl https://open.pikpikgo.com/v1/tasks/2608101909450810293847 \
  -H "Authorization: Bearer $PIKPIK_API_KEY"
json
{
  "id": "2608101909450810293847",
  "object": "image.generation",
  "created": 1786000185,
  "model": "img-std-1",
  "status": "succeeded",
  "prompt": "eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen",
  "size": "16:9",
  "quality": "2k",
  "credits": 10,
  "error": "",
  "data": [
    { "url": "https://cdn.pikpikgo.com/ai/xxxx.png", "revised_prompt": "eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen" }
  ]
}

Vollständige Beispiele

Den synchronen Weg beherrscht das offizielle OpenAI-SDK direkt – nur die baseURL ändert sich:

javascript
import OpenAI from 'openai'

const client = new OpenAI({
  apiKey: process.env.PIKPIK_API_KEY,
  baseURL: 'https://open.pikpikgo.com/v1',
  timeout: 300 * 1000,
})

// Synchron: ein Roundtrip liefert die URL, Timeout auf 300 Sekunden angehoben
const res = await client.images.generate({
  model: 'img-std-1',
  prompt: 'eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen',
  size: '1792x1024',
  n: 1,
})

console.log(res.data[0].url)

Beim asynchronen Weg setzt du Abschicken und Pollen selbst zusammen, in Node.js:

javascript
const BASE = 'https://open.pikpikgo.com/v1'
const KEY = process.env.PIKPIK_API_KEY

async function call(path, body) {
  const res = await fetch(BASE + path, {
    method: body ? 'POST' : 'GET',
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
    },
    body: body ? JSON.stringify(body) : undefined,
  })
  const json = await res.json()
  if (json.error) throw new Error(json.error.message)
  return json
}

// Absenden und auf Fertigstellung warten: alle 3 Sekunden pollen, nach 10 Minuten abbrechen
async function generateImage(prompt) {
  const job = await call('/images/generations', { prompt, size: '16:9', async: true })
  const id = job.tasks[0].id

  for (let i = 0; i < 200; i++) {
    const task = await call(`/tasks/${id}`)
    if (task.status === 'succeeded') return task.data[0].url
    if (task.status === 'failed') throw new Error(task.error || 'Generierung fehlgeschlagen')
    await new Promise((r) => setTimeout(r, 3000))
  }
  throw new Error('Zeitüberschreitung beim Warten')
}

generateImage('eine regennasse Cyberpunk-Straße bei Nacht, Neonspiegelungen').then(console.log)

Python (diesmal Video, mit größerem Poll-Intervall):

python
import os, time, requests

BASE = "https://open.pikpikgo.com/v1"
KEY = os.environ["PIKPIK_API_KEY"]
HEAD = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}


def call(path, body=None):
    if body is None:
        r = requests.get(BASE + path, headers=HEAD, timeout=30)
    else:
        r = requests.post(BASE + path, headers=HEAD, json=body, timeout=60)
    data = r.json()
    if "error" in data:
        raise RuntimeError(data["error"]["message"])
    return data


def generate_video(prompt, seconds=5):
    job = call("/video/generations", {"prompt": prompt, "duration": seconds})

    # Video dauert meist 1-5 Minuten; alle 5 Sekunden zu pollen reicht, engere Schleifen verbrauchen nur Rate-Limit
    for _ in range(200):
        task = call(f"/video/generations/{job['task_id']}")
        if task["status"] == "succeeded":
            return task["url"]
        if task["status"] == "failed":
            raise RuntimeError(task["error"] or "Generierung fehlgeschlagen")
        time.sleep(5)
    raise TimeoutError("Zeitüberschreitung beim Warten")


print(generate_video("langsame Kamerafahrt nach vorn, ein Mädchen dreht sich um und lächelt"))