dokumentation
API

Images

Markdown

Generering og redigering af billeder i OpenAI Images-format.

Komplet guide
POSThttps://api.ailoot.ai/v1/images/generations
Images
curl https://api.ailoot.ai/v1/images/generations \
  -H "Authorization: Bearer $AILOOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2.5",
    "prompt": "Akvareltegning: et fyrtårn på en klippe, daggry",
    "size": "1024x1024"
  }' 
200 OK
{
  "created": 1790812800,
  "data": [
    { "url": "https://…/content" }
  ],
  "usage": { "input_tokens": 18, "output_tokens": 1056 }
}

Godkendelse

  • Authorizationheaderpåkrævet

    Nøgle i formatet Bearer sk-…. Følgende headers kan også bruges: x-api-key eller x-goog-api-key.

Anmodningens indhold

  • modelstringpåkrævet

    Billedmodel: gpt-image-2.5-sunburst, gemini-3.1-flash-image, grok-imagine-image-2.0, qwen-image-3.0-pro, image-01, gpt-image-2, gemini-3.1-flash-lite-image, grok-imagine-image, wan2.7-image, gpt-image-2.5-sunburst-2026-09-08, gemini-3-pro-image, grok-imagine-image-quality og yderligere 4.

  • promptstringpåkrævet

    Beskrivelse af billedet.

  • nintegervalgfrit

    Antal billeder, der skal genereres. Hvert færdigt billede betales.

  • sizestringvalgfrit

    Størrelse, for eksempel 1024x1024. De tilladte størrelser afhænger af modellen.

  • qualitystringvalgfrit

    Kvalitet, hvis modellen understøtter det (for eksempel low, medium, high).

  • response_formatstringvalgfrit

    url eller b64_json — hvis modellen understøtter valget.

Redigering

POSThttps://api.ailoot.ai/v1/images/edits

Anmodning multipart/form-data: feltet image (ét eller flere billeder), prompt, model, om nødvendigt mask.

Svar

  • data[]array

    Færdige billeder: link url eller data b64_json, afhængigt af modellen.

Redigering · multipart/form-data

: "${AILOOT_IMAGE_EDIT_MODEL:?Select a model whose actual card or GET /v1/models method supports /v1/images/edits}"
curl --fail-with-body --max-time 300 \
  -D image-edit-headers.txt -o image-edit.json \
  https://api.ailoot.ai/v1/images/edits \
  -H "Authorization: Bearer $AILOOT_API_KEY" \
  -F "model=$AILOOT_IMAGE_EDIT_MODEL" \
  -F 'prompt=Keep the subject and replace the background with a sunset' \
  -F 'image=@input.png'

input.png → image-edit.json → data[] → url | b64_json

import base64
import json
import mimetypes
import os
from pathlib import Path
import time
from urllib.parse import urljoin, urlsplit
from urllib.request import Request, urlopen

origin = "https://api.ailoot.ai"
out = Path("image-edit-results")
out.mkdir(exist_ok=True)

def save_all(data):
    rows = data.get("data", [])
    if not rows:
        raise RuntimeError("No completed image data; keep the original response")
    for index, row in enumerate(rows, 1):
        if row.get("b64_json"):
            content = base64.b64decode(row["b64_json"], validate=True)
            suffix = ".png" if content.startswith(b"\x89PNG") else ".bin"
        elif row.get("url"):
            url = row["url"]
            if urlsplit(url).scheme != "https":
                raise ValueError("Expected the exact returned HTTPS image URL")
            # Signed result URLs are downloaded without sending the API key to another host.
            with urlopen(url, timeout=300) as response:
                content = response.read()
                suffix = mimetypes.guess_extension(response.headers.get_content_type()) or ".bin"
        else:
            raise RuntimeError("Image has neither url nor b64_json")
        (out / ("image-%03d" % index + suffix)).write_bytes(content)


with open("image-edit.json", encoding="utf-8") as response:
    save_all(json.load(response))

Images · async

OpenAI- og Anthropic-SDK'er gentager normalt netværksfejl og 5xx automatisk. Deaktivér det ved generering (max_retries=0) og kontrollér X-Should-Retry før et nyt forsøg. Et mistet svar betyder ikke, at anmodningen ikke blev udført.

import base64
import json
import mimetypes
import os
from pathlib import Path
import time
from urllib.parse import urljoin, urlsplit
from urllib.request import Request, urlopen

origin = "https://api.ailoot.ai"
key = os.environ["AILOOT_API_KEY"]
out = Path("image-results")
out.mkdir(exist_ok=True)

def api(url, payload=None):
    url = urljoin(origin, url)
    if urlsplit(url).scheme != "https" or urlsplit(url).netloc != "api.ailoot.ai":
        raise ValueError("Unexpected API origin")
    request = Request(url, data=None if payload is None else json.dumps(payload).encode(),
                      headers={"Authorization": "Bearer " + key, "Content-Type": "application/json"})
    with urlopen(request, timeout=300) as response:
        headers = dict(response.headers)
        data = json.load(response)
    (out / "response-headers.json").write_text(json.dumps(headers, indent=2))
    return data, headers

def save_all(data):
    rows = data.get("data", [])
    if not rows:
        raise RuntimeError("No completed image data; keep the original response")
    for index, row in enumerate(rows, 1):
        if row.get("b64_json"):
            content = base64.b64decode(row["b64_json"], validate=True)
            suffix = ".png" if content.startswith(b"\x89PNG") else ".bin"
        elif row.get("url"):
            url = row["url"]
            if urlsplit(url).scheme != "https":
                raise ValueError("Expected the exact returned HTTPS image URL")
            # Signed result URLs are downloaded without sending the API key to another host.
            with urlopen(url, timeout=300) as response:
                content = response.read()
                suffix = mimetypes.guess_extension(response.headers.get_content_type()) or ".bin"
        else:
            raise RuntimeError("Image has neither url nor b64_json")
        (out / ("image-%03d" % index + suffix)).write_bytes(content)

# One POST. If its result is unknown, preserve it and check history; do not rerun creation.
task, headers = api("/v1/images/generations/async", {
    "model": "gpt-image-2.5", "prompt": "Watercolor lighthouse at dawn", "size": "1024x1024"})
(out / "created-task.json").write_text(json.dumps(task, indent=2))
task_id = task.get("task_id") or task.get("id")
poll_url = task.get("poll_url") or headers.get("Location") or headers.get("location")
if not task_id or not poll_url:
    raise RuntimeError("Keep the create response and Request ID; do not submit again")

for poll in range(60):
    task, headers = api(poll_url)  # Read the original task with the same key.
    (out / "task-status.json").write_text(json.dumps(task, indent=2))
    if task.get("status") == "completed":
        result = task["result"]
        (out / "image-response.json").write_text(json.dumps(result, indent=2))
        save_all(result)
        break
    if task.get("status") == "failed":
        raise RuntimeError(json.dumps(task.get("error")))
    if task.get("status") != "processing" or task.get("result_pending_check"):
        raise RuntimeError("Keep the original task ID and check it later; no new POST")
    time.sleep(min(60, max(1, int(headers.get("Retry-After", headers.get("retry-after", "3"))))))
else:
    raise TimeoutError("Polling stopped; resume GET reads using created-task.json, never repeat POST")
Har du stadig spørgsmål? Send Request ID og en beskrivelse — så hjælper vi med at finde ud af det.Kontakt support