Stielpreis

So funktioniert Stielpreis

Hochzeitsangebot per API anlegen: Schlüssel, Endpunkte und Beispiel mit Antwort

Hochzeitsangebot per API anlegen: Schlüssel, Endpunkte, Beispiel mit Antwort, Fehler und was der Server rechnet. Die Stielpreis-API für Skripte und KI-Agenten.

Stand 10. November 2026 · 8 Min. Lesezeit · von Stielpreis, der Software für Hochzeitsfloristik

Ein Hochzeitsangebot per API legst du mit einer JSON-Anfrage an die Stielpreis-API v1 an: Sie erzeugt eine komplette Hochzeit mit Positionen und Kunden-Link im Konto einer Floristin. Die Anfrage nennt Blumen mit Namen und Stielzahl, aber keine Preise und keine Summen: Die rechnet der Server. Du brauchst einen API-Schlüssel, den du im Header „Authorization: Bearer“ mitschickst.

Wofür ist die API gedacht?

Gedacht ist sie für ein Programm, das beschreibt, was eine Floristin im Rechner eintippen würde: Blumen nach Namen, Stiele je Stück, Stunden, Faktor. Der Server preist die Blumen, lässt die Rechenlogik von Stielpreis laufen und liefert die Summen und den Link fürs Brautpaar zurück. Typisch ist ein KI-Agent, der aus einer Anfrage ein Angebot entwirft, oder ein Skript, das Anfragen aus einem anderen System übernimmt. Gedacht ist das für Entwicklerinnen und Floristinnen mit technischer Hilfe.

Was die API nicht tut:

  • Sie ändert, liest oder löscht keine bestehende Hochzeit. Es gibt nur das Anlegen.
  • Sie stellt weder Angebotsdokumente noch Rechnungen aus und erfasst keine Zahlungen.
  • Sie löst keine Annahme aus. Die gibt das Brautpaar selbst auf dem Link ab, siehe Annahme per Klick.
  • Sie versendet nichts. Den Link, den sie zurückgibt, schickst du selbst.

Wie meldest du dich mit dem API-Schlüssel an?

Jeder Aufruf braucht einen Schlüssel im Header:

Authorization: Bearer sp_live_XXXXXXXX

Hier steht sp_live_XXXXXXXX für deinen eigenen Schlüssel, der länger ist. Ein Schlüssel gehört zu genau einem Konto, und alles, was die API liest oder schreibt, gilt für dieses Konto. Fehlt der Schlüssel oder ist er falsch geschrieben, unbekannt oder widerrufen, antwortet der Server mit 401.

Angelegt werden Schlüssel auf der Kommandozeile mit einem Skript im Stielpreis-Code (scripts/api-key.ts, Befehle create, list und revoke). Dafür braucht es Zugriff auf die Datenbank, und das Konto muss existieren, die Floristin hat sich also einmal angemeldet. Der Schlüssel wird nur beim Anlegen einmal angezeigt. Gespeichert werden nur sein SHA-256-Wert und die ersten 16 Zeichen, mit denen er sich finden und auflisten lässt. Lege ihn in eine Umgebungsvariable und nicht in den Code, in einen Chat oder in ein Repository.

Welche Endpunkte gibt es?

Die Adresse in den Beispielen ist https://stielpreis.de.

EndpunktWas er tut
POST /api/v1/weddingsLegt eine Hochzeit mit Status Angebot an, mit Positionen, Kunden-Link, Eintrag im Verlauf und Preisgedächtnis wie beim Speichern im Rechner
GET /api/v1/catalog?q=Sucht im Katalog und in den eigenen Materialien des Kontos, bis 50 Treffer, und nennt den Preis je Stiel oder Stück, den POST ansetzen würde
GET /api/v1/schemaGibt das JSON Schema (Draft 2020-12) des POST-Bodys zurück, erzeugt aus dem Schema, mit dem der Server prüft

Im Body stehen coupleName (Pflicht, wird zur Überschrift des Angebots), optional eventDate (JJJJ-MM-TT), venue, customerAddress und showImages (Standard true), dazu positions mit 1 bis 50 Einträgen. Jede Position hat eine von vier Arten:

treatmentDas ist esFelderSteuer
werkstueckein gebundenes Stück, in der App eine Werkstattkartename, qty, materials, laborHours je Stück, optional hourlyRateCents, wastePct, factor7 % bei frischen Blumen oder Grün, 19 % wenn das ganze Material zubehoer ist
wareWare wie verkauftname, qty, unitNetPriceCents, category7 % bei schnittblume und gruen, 19 % bei zubehoer
dienstleistungAufbau, Dekoration vor Ort, eigene Beratungname, qty, unitNetPriceCents19 %
lieferungLieferung der fertigen Stückename, qty, unitNetPriceCents7 %, wenn alle anderen Positionen 7 % haben, sonst 19 % mit "taxHint": "lieferung_19"

Materialien eines Werkstücks sind catalog (name, qty) oder custom (name, category, myPriceCents, qty). Die qty einer Blume gilt für ein Stück, nicht für alle.

Hochzeitsangebot per API anlegen: ein Beispiel von der Anfrage bis zur Antwort

Der Strauß ist die Boho-Beispielkarte aus dem Rechner, dazu eine Zeile für Lieferung und Aufbau. Der Request:

curl -s https://stielpreis.de/api/v1/weddings \
  -H "Authorization: Bearer $STIELPREIS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f0d3c9e-hochzeit-lena-jonas" \
  --data @wedding.json

wedding.json:

{
  "coupleName": "Lena & Jonas",
  "eventDate": "2027-06-12",
  "venue": "Gutshof am See",
  "positions": [
    {
      "treatment": "werkstueck",
      "name": "Brautstrauß Boho",
      "qty": 1,
      "laborHours": 0,
      "hourlyRateCents": 4500,
      "wastePct": 12,
      "factor": 3,
      "materials": [
        { "kind": "catalog", "name": "Dahlie (Cafe au Lait)", "qty": 3 },
        { "kind": "catalog", "name": "Ranunkel Clooney", "qty": 5 },
        { "kind": "catalog", "name": "Lisianthus (gefuellt weiss)", "qty": 4 },
        { "kind": "catalog", "name": "Skabiose (Witwenblume)", "qty": 4 },
        { "kind": "catalog", "name": "Jungfer im Gruenen (Nigella)", "qty": 5 },
        { "kind": "catalog", "name": "Amaranth (Fuchsschwanz)", "qty": 3 },
        { "kind": "catalog", "name": "Pampasgras (Federrispe)", "qty": 2 },
        { "kind": "catalog", "name": "Olive (Olivenzweig)", "qty": 3 },
        { "kind": "catalog", "name": "Eukalyptus Parvifolia", "qty": 4 },
        { "kind": "catalog", "name": "Ruscus (Italian)", "qty": 4 },
        { "kind": "catalog", "name": "Sprayrose (Gartenrose-Typ, gefuellt)", "qty": 4 },
        { "kind": "catalog", "name": "Ammi (Falsche Bischofskraut)", "qty": 5 }
      ]
    },
    { "treatment": "dienstleistung", "name": "Lieferung und Aufbau", "qty": 1, "unitNetPriceCents": 5000 }
  ]
}

Die Antwort, 201 Created, hier gekürzt (je Material steht zusätzlich match, Kennung und Link sind Platzhalter):

{
  "weddingId": 42,
  "customerUrl": "https://stielpreis.de/a/<token>",
  "taxMode": "regelbesteuert",
  "totals": {
    "netCents": 25070,
    "taxCents": 2355,
    "grossCents": 27425,
    "blocks": [
      { "rate": 7, "netCents": 20070, "taxCents": 1405, "grossCents": 21475 },
      { "rate": 19, "netCents": 5000, "taxCents": 950, "grossCents": 5950 }
    ]
  },
  "positions": [
    { "name": "Brautstrauß Boho", "unitNetCents": 20070, "rate": 7, "taxHint": "trocken_gemischt",
      "breakdown": { "materialCents": 5973, "materialWithWasteCents": 6690, "wareneinsatzPct": 33.3, "factor": 3 } },
    { "name": "Lieferung und Aufbau", "unitNetCents": 5000, "rate": 19, "taxHint": null }
  ],
  "warnings": []
}

Nachgerechnet mit der Rechenlogik von Stielpreis (Beispielrechnung mit geschätzten Großhandelspreisen aus dem Katalog): Der Strauß kostet netto 200,70 €, die Lieferung 50,00 €, zusammen 250,70 € netto. Dazu kommen 14,05 € USt bei 7 % und 9,50 € bei 19 %, der Gesamtbetrag ist 274,25 €. Das Material mit Verschnitt ist 66,90 €, das sind 33,3 % vom Preis, unter der Warnschwelle von 40 %. trocken_gemischt steht dabei, weil das Pampasgras im Katalog als getrocknetes Material (Zubehör) geführt wird: Der Strauß bleibt bei 7 %, ob er noch als frischer Strauß gilt, klärst du mit deiner Steuerberatung. Die Grundlagen zu 7 und 19 % stehen in Umsatzsteuer in der Hochzeitsfloristik.

Der Hochzeitsrechner mit dem Brautstrauß Boho: Materialzeilen mit Menge und Einkaufspreis, rechts Summe 200,70 € netto und Gesamtbetrag 214,75 €
Der Rechner mit der Boho-Beispielkarte. Die Beispielanfrage der API bildet denselben Strauß ab: gleiche Mengen und Einkaufspreise aus dem Katalog, 200,70 € netto.
Angebotsseite des Brautpaars mit dem Brautstrauß Boho, Blumenbildern und den Summen
So sieht die Seite aus, die der Link customerUrl öffnet. Hier die Boho-Karte aus dem Rechner ohne Lieferungszeile; ein per API angelegtes Angebot erscheint auf derselben Seite.

Was rechnet der Server, und was schickst du?

Du schickst Namen, Mengen und, wo es keinen Katalogpreis gibt, deinen Einkaufspreis. Der Server nimmt den Rest aus dem Konto:

  • Preise der Katalogblumen: der Preis, den das Konto sich gemerkt hat ("match": "own"), sonst die Mitte der Katalogspanne je Stiel ("match": "catalog"). Bei custom gilt dein myPriceCents ("match": "custom").
  • Faktor, Verschnitt und Stundensatz, wenn du sie weglässt, aus den Rechner-Standards der Einstellungen.
  • Besteuerung: regelbesteuert oder Kleinunternehmerin kommt aus dem Konto, nicht aus der Anfrage.
  • Summen, Steuer je Satz und Warnungen: faktor_niedrig und wareneinsatz_hoch. Sie warnen nur, die Hochzeit wird trotzdem angelegt. Wann sie auslösen, steht in Wareneinsatz zu hoch: wann Stielpreis warnt.
  • Gültigkeit und Bedingungen: Die Gültigkeit läuft ab dem Anlegen, die Zahl der Tage kommt aus den Einstellungen. Anzahlung, Änderungsfrist und Zahlungshinweis liest der Link aus dem Konto.

Unbekannte Felder lehnt der Server ab. Ein Client, der selbst grossCents mitschickt, bekommt ein 400 statt einer stillschweigend ignorierten Zahl. Das Konto bleibt die einzige Quelle für Preise und Summen.

Wie gehst du mit Fehlern um?

StatusWann
201Angelegt, oder die Antwort eines früheren Aufrufs mit demselben Idempotency-Key (Header Idempotent-Replayed: true)
400 invalid_requestUngültiges JSON, Schemaverstoß, ungültiger Idempotency-Key oder unbekanntes Material. issues[].path zeigt auf das Feld, bei unbekannten Materialien kommen suggestions aus dem Katalog
401 unauthorizedKein gültiger Schlüssel
403 free_limitDas Konto ist im Free-Tarif und hat schon seine eine Hochzeit. Die API überschreibt sie nie, anders als der Rechner
422 idempotency_key_reusedDerselbe Key mit anderem Body

Ein unbekannter Name sieht so aus:

{
  "error": "invalid_request",
  "issues": [
    {
      "path": ["positions", 0, "materials", 0, "name"],
      "code": "unknown_material",
      "message": "\"Dahlie Blaumond\" is neither in the catalog nor among the account's own materials. Pick a name from GET /api/v1/catalog?q=..., or send it with kind \"custom\", a category and myPriceCents.",
      "suggestions": ["Dahlie", "Dahlie (Cafe au Lait)", "Dahlie Wizard of Oz", "Dahlie Karma-Serie"]
    }
  ]
}

Beim 400 korrigierst du die Anfrage anhand von issues und sendest sie erneut. Bei einem Timeout oder Netzfehler wiederholst du sie mit demselben Idempotency-Key (1 bis 255 sichtbare ASCII-Zeichen, einer je Hochzeit), dann entsteht keine zweite Hochzeit.

Wie hängst du einen KI-Agenten an?

Damit ein Agent ein Hochzeitsangebot per API anlegt, holst du das Schema einmal und gibst es ihm als Eingabeschema eines Werkzeugs, ein zweites Werkzeug sucht Blumennamen über GET /api/v1/catalog. Die Kennung des Werkzeugaufrufs eignet sich als Idempotency-Key, auf ein 400 gibst du issues als Ergebnis zurück. Ein ausführliches Beispiel steht in docs/api.md im Stielpreis-Code.

Häufige Fehler

  • Menge der Blume für alle Stücke angegeben. qty im Material gilt für ein Stück. Acht gleiche Tischgestecke sind qty: 8 an der Position.
  • Trockenware als schnittblume eingetragen. Getrocknetes, Gebleichtes, Gefärbtes und Zubehör gehören in zubehoer mit 19 %.
  • Den Namen aus dem Gedächtnis schreiben. Suche ihn mit GET /api/v1/catalog?q=, sonst kommt unknown_material.
  • Den Schlüssel im Code oder Chat hinterlassen. Wer ihn hat, legt Hochzeiten in deinem Konto an. Er lässt sich mit revoke widerrufen.
  • Den Link ungeprüft weitergeben. Die Hochzeit liegt wie jede andere unter „Meine Hochzeiten“. Prüfe Positionen und Summe im Rechner über „Bearbeiten“, bevor das Brautpaar sie sieht. Wie der Link aussieht, steht in Das Angebot als Link ans Brautpaar.

Häufige Fragen

Wie lege ich ein Hochzeitsangebot per API an?
Mit einem POST an /api/v1/weddings, dem API-Schlüssel im Header und einem JSON-Body mit coupleName und positions. Die Antwort enthält die Summen und den Link fürs Brautpaar (customerUrl).
Wofür ist die Stielpreis-API gedacht?
Ein Programm, meist ein KI-Agent oder ein Skript, legt damit ein komplettes Hochzeitsangebot im Konto einer Floristin an: Hochzeit, Positionen und Kunden-Link wie beim Speichern im Rechner.
Wie authentifiziere ich mich bei der API?
Mit einem API-Schlüssel im Header „Authorization: Bearer sp_live_...“. Ein Schlüssel gehört zu genau einem Konto. Er wird auf der Kommandozeile angelegt, eine Seite in den Einstellungen gibt es dafür nicht.
Muss meine Anfrage Preise und Summen enthalten?
Nein. Für Katalogblumen schickst du nur Name und Menge. Preise und Summen rechnet der Server. Schickst du selbst Summen, lehnt er die Anfrage mit 400 ab.
Was passiert, wenn ich die Anfrage wiederhole?
Mit einem Idempotency-Key gibt der Server beim zweiten Senden dieselbe Antwort zurück, ohne eine zweite Hochzeit anzulegen. Ohne Key entsteht bei jedem Senden eine neue, soweit dein Tarif es zulässt.
Kann ich mit der API ein Angebot ändern, Rechnungen erstellen oder die Annahme auslösen?
Nein. Die API legt Hochzeiten an und liest den Katalog und das Schema. Ändern, Dokumente, Zahlungen und die Annahme laufen weiter über Stielpreis selbst.

Weiterlesen

Alle Artikel: Stielpreis Funktionen: So rechnest du Hochzeiten durch