Die Sunventory API.

Ihre Daten gehören Ihnen, und Ihre Systeme können sie abholen: die Sunventory API liefert Baustellen, Stücklisten und Lieferungen als REST-Schnittstelle. Ihr ERP kann zusätzlich die Stückliste einer Baustelle schreiben und sich per Webhook benachrichtigen lassen, sobald Lieferungen ankommen. Erfasst wird auf der Baustelle mit der App, ausgewertet wird, wo Sie wollen.

Das Muster ist bewusst das, was Integratoren kennen: REST mit OpenAPI-Spezifikation, API-Schlüssel mit Scopes, ein idempotenter Stücklisten-Upsert über external_ref und signierte Webhooks mit At-least-once-Zustellung und Event-Deduplizierung, wie man es von Stripe und GitHub kennt.

https://app.sunventory.de/api/v1

Authentifizierung

Jede Anfrage trägt einen API-Schlüssel Ihres Kontos als Bearer-Token. Schlüssel erstellt und widerruft die Bauleitung in der Web-Plattform unter Einstellungen, API. Ein Schlüssel gilt für das ganze Konto, wird bei der Erstellung genau einmal angezeigt und verliert beim Widerruf sofort seine Gültigkeit.

Beim Erstellen wählen Sie den Zugriff: nur lesen oder lesen und schreiben. Die schreibenden Endpunkte, also Stücklisten-Import und Webhook-Verwaltung, verlangen einen Schlüssel mit Schreibzugriff. Ein Lese-Schlüssel bekommt dort 403 insufficient_scope. Bestehende Schlüssel bleiben unverändert reine Lese-Schlüssel.

curl https://app.sunventory.de/api/v1/sites \
  -H "Authorization: Bearer svk_ihr_schluessel"

Endpunkte

Lesen steht jedem Schlüssel offen, Schreiben nur Schlüsseln mit Schreibzugriff. Listen sind seitenweise abrufbar (limit bis 500, offset), Lieferungen zusätzlich filterbar über site_id, supplier, from, to (jeweils JJJJ-MM-TT) und status (pending oder confirmed).

  • GET /sites Alle Baustellen des Kontos.
  • GET /sites/{id} Eine Baustelle.
  • GET /sites/{id}/bom Die Stückliste mit Soll, bestätigter und offener Menge je Position.
  • PUT /sites/{id}/bom Stückliste importieren: Positionen anlegen oder aktualisieren, idempotent über external_ref. Braucht Schreibzugriff.
  • GET /deliveries Lieferungen mit Positionen und Lieferschein-Fotos, filterbar nach Baustelle, Lieferant, Zeitraum und Status.
  • GET /deliveries/{id} Eine Lieferung.
  • GET /deliveries.csv Dieselben Lieferungen als CSV, eine Zeile je Position.
  • GET/POST/DELETE /webhooks Webhooks verwalten. Braucht Schreibzugriff.
  • POST /webhooks/{id}/test Ein signiertes Test-Event an den Endpunkt schicken.

Die vollständige Beschreibung aller Felder liefert die Maschine selbst: openapi.json im OpenAPI-3.1-Format, ohne Schlüssel abrufbar.

Beispiele

Lieferfortschritt einer Baustelle

curl "https://app.sunventory.de/api/v1/sites/{id}/bom" \
  -H "Authorization: Bearer svk_…"
{
  "data": [{
    "supplier": "Canadian Solar",
    "product": "HiKu7 CS7L-590MS 590W bifazial",
    "planned_quantity": 169500,
    "delivered_quantity": 8297,
    "pending_quantity": 1188,
    "last_delivery_at": "2026-05-27",
    …
  }]
}

Bestätigte Lieferungen eines Monats als CSV

curl "https://app.sunventory.de/api/v1/deliveries.csv?status=confirmed&from=2026-07-01&to=2026-07-31" \
  -H "Authorization: Bearer svk_…" -o lieferungen.csv

Jede Lieferung führt ihre Lieferschein-Fotos als signierte, zeitlich begrenzte URLs mit. Wer den Beleg zur Buchung braucht, lädt ihn direkt aus der Antwort.

Stückliste importieren

PUT /sites/{id}/bom übernimmt Bestellpositionen aus Ihrem ERP in die Stückliste der Baustelle, bis zu 1000 Positionen je Anfrage, alles in einer Transaktion. Der Anker ist external_ref, zum Beispiel Bestellnummer und Zeile aus Dynamics 365: Positionen mit bekannter Referenz werden aktualisiert, neue werden angelegt. Geben Sie jeder Position eine stabile external_ref, dann darf derselbe Import beliebig oft laufen und erzeugt nie Duplikate; nur Positionen ohne Referenz werden bei jedem Lauf neu angelegt. Eine Aktualisierung übernimmt die Position vollständig, auch leere optionale Felder überschreiben den Bestand.

curl -X PUT "https://app.sunventory.de/api/v1/sites/{id}/bom" \
  -H "Authorization: Bearer svk_…" \
  -H "Content-Type: application/json" \
  -d '{
    "positions": [
      { "external_ref": "PO-4711/10", "supplier": "Canadian Solar",
        "product": "PV-Modul CS7N 700 MB-T", "category": "PV-Module",
        "planned_quantity": 196000, "unit": "Stück" },
      { "external_ref": "PO-4711/20", "supplier": "LAPP",
        "product": "Solarkabel H1Z2Z2-K 6 mm²",
        "planned_quantity": 84000, "unit": "m" }
    ]
  }'
{ "created": 2, "updated": 0, "data": [ … ] }

Die Antwort führt die betroffenen Positionen in denselben Feldern wie GET /sites/{id}/bom, inklusive bereits gelieferter Mengen. Beim zweiten identischen Lauf meldet sie "created": 0, "updated": 2. Zwei Regeln geben dem Import seine Sicherheit: Positionen mit verknüpften Lieferungen behalten ihre ID, der Liefernachweis bleibt also stehen. Und die API löscht nie. Positionen, die im Import fehlen, bleiben unberührt; entfernt wird bewusst nur in der App.

Webhooks

Statt zu pollen, lassen Sie sich benachrichtigen: ein Webhook ruft Ihr System auf, sobald auf der Baustelle eine Lieferung erfasst (delivery.created) oder von der Bauleitung bestätigt (delivery.confirmed) wird. Registriert wird mit einem Schreib-Schlüssel:

curl -X POST https://app.sunventory.de/api/v1/webhooks \
  -H "Authorization: Bearer svk_…" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://erp.example.com/hooks/sunventory",
       "events": ["delivery.created", "delivery.confirmed"] }'

Die Antwort enthält genau einmal das Signatur-Secret (whsec_…). Jedes Event kommt als POST mit diesem Umschlag; data ist die Lieferung in denselben Feldern wie GET /deliveries/{id}, inklusive frisch signierter Foto-URLs:

{
  "event_id": "8f14e45f-…",
  "event": "delivery.created",
  "timestamp": "2026-08-26T09:41:00.000Z",
  "webhook_id": "6512bd43-…",
  "data": { … }
}

Die Zustellung ist at-least-once, wie bei Stripe und GitHub: dasselbe Event kann mehrfach ankommen, trägt dann aber dieselbe event_id. Ihr Konsument dedupliziert also über die event_id und antwortet mit einem 2xx innerhalb von 10 Sekunden. Bei Fehlern versucht Sunventory die Zustellung drei weitere Male, nach 1, 10 und 60 Minuten. Nach 20 Fehlschlägen in Folge wird der Webhook deaktiviert; den Zustand sehen Sie unter Einstellungen, API und per GET /webhooks.

Jede Zustellung ist signiert. Der Header X-Sunventory-Signature: t=<unix>,v1=<hmac> trägt einen HMAC-SHA256 über t + "." + rohen Body mit Ihrem Secret. Prüfen Sie die Signatur und lehnen Sie Zeitstempel ab, die älter als etwa 5 Minuten sind, das schützt vor Replays:

# Python
import hmac, hashlib, time

def verify(header, secret, raw_body):
    t, v1 = (part.split("=", 1)[1] for part in header.split(","))
    mac = hmac.new(secret.encode(), (t + ".").encode() + raw_body, hashlib.sha256)
    fresh = abs(time.time() - int(t)) < 300
    return fresh and hmac.compare_digest(mac.hexdigest(), v1)

Zum Einrichten schickt POST /webhooks/{id}/test ein signiertes Test-Event und meldet direkt zurück, ob Ihr Endpunkt es angenommen hat.

Business Central, SAP und Co.

Die API ist bewusst schlicht gehalten: HTTPS, JSON, CSV. Damit spricht sie jedes System, das Wareneingänge aufnehmen kann, ohne eigenen Konnektor.

  • Microsoft Dynamics 365 Business Central liest die Endpunkte per Power Automate oder direkt aus AL über den HttpClient.
  • SAP bindet die Schnittstelle über die Integration Suite (CPI) oder jede andere HTTP-fähige Middleware an.
  • Für alles andere ist der CSV-Export der kürzeste Weg: eine Zeile je Position, UTF-8, direkt importierbar.

Sie planen eine Anbindung und wollen sie nicht selbst bauen? Schreiben Sie uns, wir richten sie im Rahmen eines Pilotprojekts mit ein.

Verlässlichkeit

  • Version 1 ist ein Vertrag: Felder kommen hinzu, werden aber nicht umbenannt und nicht entfernt.
  • Schreiben können nur Schlüssel mit Schreibzugriff, und nur die Stückliste. Erfassung und Bestätigung bleiben in der App und der Web-Plattform, gelöscht wird über die API nie, der Nachweis bleibt unverändert.
  • Je Schlüssel sind 120 Anfragen pro Minute frei, genug für minütliche Abgleiche. Antworten tragen die üblichen RateLimit-Header.
  • Betrieb in einem Rechenzentrum in Deutschland, wie die ganze Plattform. Details in der Datenschutzerklärung.