API Dokumentation

Programmieren Sie Zugriff auf Immopix-Funktionen. Bearbeiten Sie Bilder, verwalten Sie Properties und integrieren Sie KI-Optimierungen in Ihren Workflow.

Hinweis

Die API ist in allen Paketen enthalten. Jeder API-Aufruf verbraucht Credits wie eine Bearbeitung in der Web-Oberfläche.

Sie möchten Immopix ohne eigene Programmierung in einem KI-Assistenten nutzen? Dafür gibt es den Immopix Connector.

Authentifizierung

Die Immopix API verwendet Token-basierte Authentifizierung. Ihr API-Token kann in den Account-Einstellungen generiert und widerrufen werden.

Senden Sie Ihren Token im Authorization Header bei jeder Anfrage:

Authorization: Token ihr_api_token

Sichere Wiederholungen

Wenn Ihre Verbindung abbricht, senden Sie dieselbe Anfrage mit demselben Idempotency-Key erneut. Immopix legt das Objekt oder den Bearbeitungsauftrag dann nicht doppelt an.

Der optionale Header gilt für POST /properties, POST /photos/upload und POST /photos/edit.

Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
  • Verwenden Sie für jeden gewünschten Vorgang einen neuen Schlüssel.
  • Der Schlüssel darf 1 bis 128 sichtbare ASCII-Zeichen ohne Leerzeichen enthalten. Eine UUID eignet sich dafür.
  • Eine Wiederholung mit denselben Daten gibt die gespeicherte Antwort zurück. Der Response-Header Idempotency-Replayed: true kennzeichnet diese Antwort.
  • Wenn Sie die Daten ändern, verwenden Sie einen neuen Schlüssel. Andernfalls antwortet die API mit 409 idempotency_conflict.
  • Die API speichert auch fachliche Fehler für diesen Schlüssel. Verwenden Sie nach einer Korrektur, zum Beispiel nach einem Guthabenkauf, einen neuen Schlüssel.

Fehlerbehandlung

Bei Fehlern gibt die API ein JSON-Objekt mit einem error Feld zurück:

{
  "error": {
    "code": "insufficient_credits",
    "message": "Keine Credits verfügbar"
  }
}

Fehler-Codes

Code Status Beschreibung
invalid_token401Token fehlt oder ist ungültig
insufficient_credits402Keine Credits verfügbar
invalid_preset400Ungültiger Preset-Key
image_too_large400Bild überschreitet 20MB
image_required400Weder image_base64 noch image_url angegeben
rate_limit_exceeded429Rate Limit erreicht
invalid_idempotency_key400Schlüssel ist leer, zu lang oder enthält Leerzeichen
idempotency_conflict409Derselbe Schlüssel wurde mit anderen Daten verwendet
idempotency_in_progress409Der erste Aufruf läuft noch. Wiederholen Sie die Anfrage nach der Zeit im Retry-After Header
conflict400presets und custom_prompt gleichzeitig angegeben
not_found404Ressource nicht gefunden

Paginierung

Listen-Endpoints unterstützen Cursor-basierte Paginierung mit limit (Standard: 20, Max: 100) und cursor Parametern.

{
  "data": [...],
  "pagination": {
    "has_more": true,
    "next_cursor": "abc123"
  }
}

Rate Limits

60 Anfragen pro Minute pro Token. Bei Überschreitung: 429 Status mit Retry-After Header.

Bild-Limits: Max 20MB, Formate JPEG/PNG/WebP, Max 8192x8192 Pixel


Tutorial: Bild bearbeiten

Der typische Workflow: Bild hochladen, Job abwarten, Ergebnis abrufen.

Python

import base64
import time
import uuid

import requests

API_TOKEN = "ihr_api_token"
headers = {"Authorization": f"Token {API_TOKEN}"}
edit_headers = {**headers, "Idempotency-Key": str(uuid.uuid4())}

# 1. Bild hochladen
with open("foto.jpg", "rb") as f:
    image_base64 = base64.b64encode(f.read()).decode()

response = requests.post(
    "https://immopix.ai/api/v1/photos/edit",
    headers=edit_headers,
    json={
        "image_base64": image_base64,
        "presets": "auto"  # oder: ["sunshine", "optimize"]
    }
)
job = response.json()
job_id = job["job_id"]
print(f"Job gestartet: {job_id}")

# 2. Job-Status abfragen (Polling)
while True:
    response = requests.get(
        f"https://immopix.ai/api/v1/jobs/{job_id}",
        headers=headers
    )
    job = response.json()

    if job["status"] == "completed":
        print(f"Fertig: {job['result_url']}")
        break
    elif job["status"] == "failed":
        print(f"Fehler: {job['error_message']}")
        break

    time.sleep(2)

cURL

# 1. Bild hochladen
curl -X POST "https://immopix.ai/api/v1/photos/edit" \
  -H "Authorization: Token ihr_api_token" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/foto.jpg",
    "presets": "auto"
  }'

# Response: {"job_id": "job_abc123", "status": "pending", ...}

# 2. Job-Status abfragen
curl "https://immopix.ai/api/v1/jobs/job_abc123" \
  -H "Authorization: Token ihr_api_token"

Eigene Anweisungen (custom_prompt)

Statt Presets können Sie auch eigene Anweisungen übergeben:

curl -X POST "https://immopix.ai/api/v1/photos/edit" \
  -H "Authorization: Token ihr_api_token" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/foto.jpg",
    "custom_prompt": "Rasen grün machen, Himmel blau, Mülltonnen entfernen"
  }'

Tipp: Nutzen Sie Webhooks anstelle von Polling, um bei Job-Abschluss benachrichtigt zu werden.


Properties

Properties sind Container für Fotos einer Immobilie.

GET /api/v1/properties

Listet alle Properties auf.

Query-Parameter

queryFiltert nach Property-Name. Jeder Teil des Namens passt, Groß- und Kleinschreibung spielt keine Rolle.
{
  "data": [
    {
      "id": "prp_abc123",
      "name": "Musterstraße 42",
      "created_at": "2024-01-15T10:30:00Z",
      "photo_count": 12
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null
  }
}
POST /api/v1/properties

Erstellt eine neue Property.

Request Body

name *Name der Property
{
  "id": "prp_abc123",
  "name": "Musterstraße 42",
  "created_at": "2024-01-15T10:30:00Z",
  "photo_count": 0
}
GET /api/v1/properties/{id}

Property-Details mit verschachtelter Foto-Liste.

{
  "id": "prp_abc123",
  "name": "Musterstraße 42",
  "created_at": "2024-01-15T10:30:00Z",
  "photo_count": 3,
  "photos": [
    {
      "id": "pht_xyz789",
      "title": "Wohnzimmer",
      "image_type": "indoor",
      "thumbnail_url": "https://..."
    }
  ]
}
PATCH /api/v1/properties/{id}

Aktualisiert eine Property. Parameter: name

DELETE /api/v1/properties/{id}

Löscht Property und alle zugehörigen Fotos. Unwiderruflich.

Photos

GET /api/v1/properties/{id}/photos

Listet alle Fotos einer Property auf.

Query-Parameter

image_typeFiltert nach Bildtyp. Werte: indoor, outdoor, floorplan, other. Ein anderer Wert ergibt 400 validation_error.
{
  "data": [
    {
      "id": "pht_xyz789",
      "title": "Wohnzimmer",
      "image_type": "indoor",
      "current_url": "https://...",
      "thumbnail_url": "https://...",
      "created_at": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null
  }
}
GET /api/v1/photos/{id}

Foto-Details mit Revision-History und URLs.

{
  "id": "pht_xyz789",
  "title": "Wohnzimmer",
  "image_type": "indoor",
  "current_url": "https://...",
  "thumbnail_url": "https://...",
  "revisions": [
    {
      "id": "rev_abc123",
      "version": 1,
      "is_original": false,
      "url": "https://...",
      "created_at": "2024-01-15T10:35:00Z"
    }
  ],
  "created_at": "2024-01-15T10:30:00Z"
}
Hinweis: Bild-URLs sind signiert und laufen nach 60 Minuten ab.
POST /api/v1/photos/edit

Sendet ein Bild zur KI-Optimierung.

Request Body

image_base64Base64-kodierte Bilddaten
image_urlURL zum Bild (öffentlich zugänglich)
photo_idBestehendes Foto erneut bearbeiten
presetsArray von Preset-Keys oder "auto". Alle Keys liefert GET /presets.
custom_promptEigene Anweisungen (max. 1000 Zeichen). Kernvorgaben werden automatisch angewendet.
property_idMit Property verknüpfen
edit_mode"outdoor" (Standard), "indoor" oder "floorplan"
lock_camera_angleKamerawinkel beibehalten (boolean)
room_typeRaumtyp für Möblierung. Werte: living_room, bedroom, kitchen, bathroom, kids_room, dining_room, hallway, home_office (privates Arbeitszimmer), office (gewerbliches Büro), garage, basement, dressing_room. Ohne Angabe wird automatisch erkannt.
furniture_styleMöbelstil für Staging. Werte: modern, skandinavisch, klassisch, landhausstil, industriell. Ohne Angabe wird automatisch erkannt.
intensity"normal" (Standard) oder "subtle" für dezentere Bearbeitung.
resolution"2K" (Standard) oder "4K". 4K verbraucht 2 Credits.

Sie müssen image_base64, image_url oder photo_id angeben.

presets und custom_prompt sind gegenseitig ausschließend – verwenden Sie eines von beiden. Ohne Angabe werden Standard-Presets verwendet.

Die aktuellen Werte für presets, room_type und furniture_style rufen Sie über GET /presets ab.

Verfügbare Presets

Verwenden Sie "auto" für automatische Erkennung, oder wählen Sie spezifische Presets. Die vollständige, aktuelle Liste liefert GET /presets.

Response

{
  "job_id": "job_abc123",
  "photo_id": "pht_xyz789",
  "status": "pending"
}
POST /api/v1/photos/upload

Lädt ein Foto hoch, ohne eine Bearbeitung auszulösen. Keine Credits werden verbraucht. Das Foto wird gespeichert, kategorisiert und steht im Dashboard zur Bearbeitung bereit.

Request Body

image_base64Base64-kodierte Bilddaten
image_urlURL zum Bild (öffentlich zugänglich)
property_idMit Property verknüpfen (optional, Standard: "API Uploads")

Sie müssen image_base64 oder image_url angeben (genau eines).

Response (201)

{
  "photo_id": "pht_xyz789",
  "property_id": "prp_abc123",
  "property_url": "https://immopix.ai/app/property/prp_abc123/"
}
DELETE /api/v1/photos/{id}

Löscht Foto und alle Revisionen.

Jobs

GET /api/v1/jobs/{job_id}

Job-Status abfragen. Status: pending | processing | completed | failed

{
  "job_id": "job_abc123",
  "photo_id": "pht_xyz789",
  "status": "completed",
  "presets": ["sunshine", "optimize"],
  "result_url": "https://...",
  "width": 1920,
  "height": 1080,
  "error_message": null,
  "created_at": "2024-01-15T10:30:00Z"
}
result_url, width, height nur bei status: "completed". error_message nur bei status: "failed".

Presets

Dieser Endpoint liefert alle Optionen, die eine Bearbeitung annimmt. So halten Sie Ihre Integration aktuell, ohne die Werte fest einzutragen.

GET /api/v1/presets

Listet alle Presets, Möbelstile und Raumtypen auf.

Response

{
  "presets": [
    {
      "key": "optimize",
      "edit_mode": "outdoor",
      "label": "Belichtung optimieren",
      "description": "Helligkeit, Farben & Kontrast verbessern"
    },
    {
      "key": "staging",
      "edit_mode": "indoor",
      "label": "Virtuell möblieren",
      "description": "Leere Räume mit passenden Möbeln einrichten"
    },
    {
      "key": "floorplan_3d",
      "edit_mode": "floorplan",
      "label": "3D Grundriss",
      "description": "2D-Grundriss in eine 3D-Ansicht umwandeln"
    }
    ...
  ],
  "furniture_styles": ["modern", "skandinavisch", ...],
  "room_types": [
    {"key": "living_room", "label": "Wohnzimmer"},
    {"key": "bedroom", "label": "Schlafzimmer"}
    ...
  ]
}

Die key-Werte setzen Sie direkt in POST /api/v1/photos/edit ein: presets aus presets, room_type aus room_types und furniture_style aus furniture_styles.

edit_mode ordnet jedes Preset einem Modus zu: outdoor, indoor oder floorplan. Verwenden Sie nur Presets aus dem Modus, den Sie in der Anfrage senden.

Ohne presets oder mit "auto" wählt Immopix passende Presets für das Bild aus.


Webhooks

Webhook-URLs werden in den Account-Einstellungen konfiguriert. Events: job.completed, job.failed

{
  "event": "job.completed",
  "job": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "photo_id": "pht_xyz789",
    "status": "completed",
    "presets": ["sunshine", "optimize"],
    "result_url": "https://...",
    "width": 1920,
    "height": 1080,
    "created_at": "2024-01-15T10:30:00Z"
  }
}
Retry-Policy: 3 Versuche mit exponentiellem Backoff (1min, 5min, 30min). Nach 3 Fehlschlägen wird der Webhook deaktiviert.

Signatur-Verifizierung

Jeder Webhook enthält einen X-Immopix-Signature Header (HMAC-SHA256).

Python
import hmac
import hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

# In Ihrem Webhook-Handler:
signature = request.headers.get("X-Immopix-Signature")
if not verify_signature(request.data, signature, WEBHOOK_SECRET):
    return "Invalid signature", 401
Node.js
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

Credits

Die API verwendet dasselbe Credit-System wie die Web-Oberfläche. Details finden Sie auf unserer Preisseite. Bei einem insufficient_credits-Fehler sind Ihre Credits aufgebraucht.