v1 · Public PreviewLese- & SchreibzugriffJSON · UTF-8

Pfeffersack REST API

Programmatischer Zugriff auf Rechnungen, Dokumente, Belege und Buchungen Ihres Pfeffersack-Accounts. Die Endpoints sind nach Sektion getrennt — GmbHs nutzen die doppelte Buchführung (Journal), Einzelunternehmen die vereinfachte Buchungs-Tabelle. Neben Lesezugriff unterstützt die API Write-Endpoints für Agents und Integrationen: Entwürfe für Journal, Rechnungen und Offerten, Kontakte, Anlagen und Beleg-Uploads — abgesichert über Scopes und Idempotenz.

Quickstart

  1. API-Key erstellen unter Einstellungen → Integrationen → API-Keys. Der Key wird nur einmal angezeigt.
  2. Den Key im Authorization-Header jedes Requests mitsenden.
  3. Alle Responses sind JSON mit Content-Type: application/json; charset=utf-8.

Erster Request

curl -H "Authorization: Bearer pfs_live_IHR_KEY" \
  "https://pfeffersack.ch/api/v1/gmbh/invoices?limit=5"

Authentifizierung

Die API nutzt Bearer-Token-Authentifizierung. Der Key wird einmalig bei der Erstellung angezeigt — speichern Sie ihn an einem sicheren Ort (Passwort-Manager oder Secrets- Store Ihres Deployment-Systems).

Authorization: Bearer pfs_live_AbCdEf0123456789...

Key-Format

PrefixTypBeschreibung
pfs_live_stringProduktiv-Key. Lesezugriff immer; Schreibzugriff nur mit expliziten Scopes (siehe Schreibzugriff).
pfs_test_stringReserviert für zukünftigen Test-Mode (noch nicht aktiv).

Zeichensatz nach Prefix: A–Z a–z 0–9 _ (Base62 + Underscore). Länge: 32+ Zeichen. Keys werden serverseitig nur als SHA-256-Hash gespeichert.

Fehlgeschlagene Authentifizierung

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="Pfeffersack API"
Content-Type: application/json

{ "success": false, "error": "Unauthorized" }

Antworten sind bewusst uniform (gleicher Shape, gleiche Latenz) — das verhindert User-Enumeration und Timing-Attacks.

Konventionen

  • Base-URL: https://pfeffersack.ch/api/v1 — ausschließlich HTTPS. Plain-HTTP-Requests werden abgewiesen.
  • Timestamps: ISO-8601 in UTC mit Z-Suffix (z. B. 2026-04-02T14:21:00.000Z) für Datetime-Felder,YYYY-MM-DD für reine Datumsfelder.
  • Geldbeträge: JSON number mit bis zu 2 Nachkommastellen (z. B. 1621.50). Keine Minor-Units. Null = kein Wert, 0 = explizit null.
  • Währung: ISO-4217 (meist CHF, optional EUR, USD).
  • IDs: Integer, auto-incrementiert pro User- Scope. IDs sind innerhalb Ihres Accounts eindeutig, aber nicht global.
  • Sortierung: Listen sind absteigend nach Datum + ID sortiert (neueste zuerst). Reihenfolge ist stabil über Pages hinweg.
  • CORS: Die API ist für Server-to-Server gedacht. Browser-Aufrufe von Drittdomains sind nicht erlaubt — der API-Key würde sonst im Client-Bundle leaken.
  • Unbekannte Felder: Ignorieren. Neue Felder können additiv hinzukommen und gelten nicht als Breaking Change.

Rate Limits

Pro API-Key: 120 Requests pro Minute (rollendes Fenster). Bei Überschreitung 429 Too Many Requests mit Retry-After (Sekunden bis Reset).

HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Reset: 1713540000
Content-Type: application/json

{ "success": false, "error": "Zu viele Anfragen. Bitte versuchen Sie es später erneut." }

Write-Endpoints sind strenger gedrosselt: 30 Requests pro Minute für alle POSTs (Journal, Rechnungen, Buchungen, Kontakte, Anlagen), 10 Requests pro Minute für Datei-Uploads (Belege). Der Dry-Run /journal/validate erlaubt 60/min.

Zusätzlich gilt ein IP-basierter Vorab-Limit von 30 Requests pro Minute für unautorisierte Anfragen (fehlender/ungültiger Key). Das schützt vor Brute-Force auf den Key-Lookup.

Empfehlung: Implementieren Sie exponentielles Backoff mit Jitter. Respektieren Sie Retry-After strikt — Requests während der Sperrzeit zählen in den nächsten Window- Zähler.

Pagination

Alle List-Endpoints sind paginiert. Response-Body enthält strukturierte Pagination-Metadaten im Feld pagination.

ParameterTypDefaultBeschreibung
pageinteger11-basierte Seitennummer.
limitinteger (1–100)25Einträge pro Seite. Werte außerhalb des Bereichs werden automatisch geclampt.
{
  "success": true,
  "data": [ /* ... */ ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 142,
    "total_pages": 6,
    "has_next": true,
    "has_prev": false
  }
}

Fehler-Format

Alle Fehler folgen demselben JSON-Envelope — success=false plus lokalisierte error-Meldung.

{ "success": false, "error": "Rechnung nicht gefunden" }

Fehlermeldungen sind menschenlesbar (Deutsch) und können sich ändern. Unterscheiden Sie Fehlerfälle über den HTTP-Status, nicht über den Text.

Status Codes

CodeTypBeschreibung
200 OKsuccessRequest erfolgreich, Response-Body enthält Daten.
400 Bad RequestclientUngültige Eingabe (z. B. Route-Parameter keine positive Ganzzahl).
401 UnauthorizedclientKein, ungültiger oder widerrufener API-Key. Header prüfen.
403 ForbiddenclientKey existiert, hat aber keinen Zugriff auf diese Ressource (z. B. GmbH-Endpoint mit Einzelfirma-Key).
404 Not FoundclientRessource existiert nicht oder gehört nicht zu Ihrem Account.
409 ConflictclientDuplikat (z. B. Rechnungsnummer bereits vergeben) oder Idempotency-Key mit abweichendem Request wiederverwendet.
422 Unprocessable EntityclientSyntaktisch gültig, aber Geschäftsregel verletzt (z. B. Soll ≠ Haben, Konto nicht bebuchbar, kein offenes Geschäftsjahr).
429 Too Many RequestsclientRate-Limit überschritten. Retry-After respektieren.
500 Internal Server ErrorserverUnerwarteter Serverfehler. Mit exponentiellem Backoff retrien.

Schreibzugriff (Write-Endpoints)

Die API erstellt konsequent Entwürfe: Journal-Einträge entstehen mit status="draft" und können nur in der App geprüft und gebucht werden. So können Agents vorbereiten, ohne dass ungeprüfte Daten im Hauptbuch landen. Buchungen der Einzelfirma kennen keinen Entwurfsstatus und sind sofort final (dokumentierte Ausnahme).

Scopes

Schreiben erfordert einen expliziten Write-Scope am API-Key (wählbar beim Erstellen des Keys). Keys ohne Scopes sind read-only — bestehende Keys erhalten also nie ungewollt Schreibrechte. Fehlt der Scope, antwortet der Endpoint mit 403 Forbidden.

ScopeTypBeschreibung
write:journalscopeGmbH-Journalentwürfe erstellen und validieren.
write:invoicesscopeRechnungs- und Offertenentwürfe (GmbH + Einzelfirma).
write:bookingsscopeEinzelbuchungen der Einzelfirma erstellen.
write:contactsscopeDebitoren, Kreditoren und Kunden anlegen.
write:assetsscopeAnlagen erfassen (GmbH).
write:documentsscopeBelege hochladen (GmbH-Dokumente + Standard-Belege).
write:*scopeAlle Schreibrechte (Convenience-Wildcard).

Idempotenz

Alle JSON-POSTs unterstützen den Header Idempotency-Key (Client- generierte UUID, dringend empfohlen). Netzwerk-Retries erzeugen damit garantiert keine doppelten Buchungen oder Rechnungen:

  • Gleicher Key + gleicher Request → die gespeicherte Response wird 1:1 wiederholt (Header Idempotency-Replayed: true).
  • Gleicher Key + abweichender Request → 409 Conflict.
  • Serverfehler (5xx) werden nie gespeichert — Retries bleiben möglich.
  • Dedup-Fenster: 24 Stunden.
curl -X POST \
  -H "Authorization: Bearer pfs_live_IHR_KEY" \
  -H "Idempotency-Key: 4c1f9e64-2b7a-4f30-9a51-8f4a1c2d3e5f" \
  -H "Content-Type: application/json" \
  -d '{
    "entry_date": "2026-07-08",
    "description": "Abschreibung Lieferwagen 2026",
    "lines": [
      { "account_id": 6800, "debit": 5000, "credit": 0 },
      { "account_id": 1530, "debit": 0, "credit": 5000 }
    ]
  }' \
  "https://pfeffersack.ch/api/v1/gmbh/journal"

Write-Endpoints im Überblick

EndpointTypBeschreibung
POST /v1/gmbh/journalwrite:journalJournalentwurf (Soll/Haben, min. 2 Zeilen, ausgeglichen, CHF). Status immer 'draft'.
POST /v1/gmbh/journal/validatewrite:journalDry-Run: identische Validierung ohne Insert. Liefert { valid, balanced, totals, errors[] }.
POST /v1/gmbh/invoiceswrite:invoicesRechnungs-/Offertenentwurf. Offerte = ohne Ledger-Wirkung; Rechnung erzeugt wie in der App Journal-Eintrag + Offenen Posten (Draft, stornierbar).
POST /v1/standard/invoiceswrite:invoicesRechnung der Einzelfirma (startet als 'Unbezahlt'; kein PDF-Upload).
POST /v1/standard/bookingswrite:bookingsEinzelbuchung (sofort final). FX-Umrechnung + MWST-Split wie in der App.
POST /v1/gmbh/debtors · /v1/gmbh/creditorswrite:contactsDebitor/Kreditor anlegen (Nummer wird autogeneriert).
POST /v1/standard/customerswrite:contactsKunde der Einzelfirma anlegen.
POST /v1/gmbh/assetswrite:assetsAnlage erfassen. Abschreibungs-Vorschau: GET /v1/gmbh/assets/{id}/depreciation-schedule (kein Buchen — das bleibt dem Jahresabschluss vorbehalten).
POST /v1/gmbh/documents · /v1/standard/belegewrite:documentsBeleg hochladen (multipart/form-data, Feld 'file', max. 25 MB). OCR startet automatisch; Status via GET pollen (processing_status).

Alle Writes validieren referenzierte IDs (Konten, Debitoren, Kreditoren, MWST-Sätze) gegen Ihren Account — fremde IDs führen zu 422. Periodensperren und geschlossene Geschäftsjahre werden mit 403 abgewiesen. Jeder GmbH-Write wird im Audit-Log festgehalten.

GmbH Endpoints

Erfordern einen API-Key eines Accounts mit business_type = "gmbh". Andernfalls 403 Forbidden. Sensible interne Felder (PDF-Blobs, S3-Keys, Creator-IDs) werden grundsätzlich nicht exponiert.

GET

/v1/gmbh/invoices

business_type = gmbh

Paginierte Liste von GmbH-Rechnungen (eingehend und ausgehend).

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
statusenumdraft, sent, paid, partial, overdue, void, cancelled
document_typeenuminvoice, offerte, proforma, credit_note
fromdate (YYYY-MM-DD)Filter: invoice_date ≥ from
todate (YYYY-MM-DD)Filter: invoice_date ≤ to
curl -H "Authorization: Bearer $PFS_KEY" \
  "https://pfeffersack.ch/api/v1/gmbh/invoices?status=paid&from=2026-01-01"
{
  "success": true,
  "data": [
    {
      "id": 142,
      "invoice_number": "R-2026-001",
      "invoice_type": "outgoing",
      "document_type": "invoice",
      "invoice_date": "2026-03-15",
      "due_date": "2026-04-14",
      "valid_until": null,
      "debtor_id": 23,
      "creditor_id": null,
      "net_amount": 1500.00,
      "vat_amount": 121.50,
      "gross_amount": 1621.50,
      "paid_amount": 1621.50,
      "currency": "CHF",
      "vat_treatment": "normal",
      "price_type": "net",
      "discount_percentage": 0,
      "status": "paid",
      "reference": "RF18 5390 0754 7034",
      "notes": null,
      "items": [
        { "description": "Beratung März", "quantity": 10, "unit_price": 150.00, "vat_rate": 8.1 }
      ],
      "sent_at": "2026-03-15T09:12:00.000Z",
      "paid_at": "2026-04-02T14:21:00.000Z",
      "created_at": "2026-03-15T09:10:00.000Z",
      "updated_at": "2026-04-02T14:21:00.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/gmbh/invoices/{id}

business_type = gmbh

Einzelne Rechnung. 404 wenn die ID nicht existiert oder nicht zu Ihrem Account gehört. 400 wenn {id} keine positive Ganzzahl ist.

GET

/v1/gmbh/documents

business_type = gmbh

Paginierte Liste hochgeladener Dokumente (Belegerfassung mit OCR) — inklusive Dokumenten, die noch nicht verbucht sind. Solange kein Journaleintrag existiert, ist journal_entry_id null. Damit lässt sich z. B. programmatisch prüfen, welche Belege bereits erfasst bzw. verarbeitet sind. OCR-Rohtext und S3-Keys werden nicht exponiert.

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
document_typeenuminvoice_in, invoice_out, receipt, bank_statement, contract, expense_report, other
processing_statusenumOCR-Status: pending, processing, completed, failed
has_journal_entrytrue | falseNur verbuchte (true) bzw. noch unverbuchte (false) Dokumente.
fromdate (YYYY-MM-DD)Filter: document_date ≥ from
todate (YYYY-MM-DD)Filter: document_date ≤ to
curl -H "Authorization: Bearer $PFS_KEY" \
  "https://pfeffersack.ch/api/v1/gmbh/documents?has_journal_entry=false&processing_status=completed"
{
  "success": true,
  "data": [
    {
      "id": 3104,
      "filename": "rechnung-hosting-april.pdf",
      "mime_type": "application/pdf",
      "file_size": 92144,
      "document_type": "invoice_in",
      "vendor_name": "Hostpoint AG",
      "document_date": "2026-04-03",
      "total_amount": 29.00,
      "currency": "CHF",
      "vat_amount": 2.17,
      "processing_status": "completed",
      "journal_entry_id": null,
      "created_at": "2026-04-05T10:18:42.000Z",
      "updated_at": "2026-04-05T10:18:55.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/gmbh/documents/{id}

business_type = gmbh

Einzelnes Dokument. 404 wenn die ID nicht existiert oder nicht zu Ihrem Account gehört.

GET

/v1/gmbh/belege

business_type = gmbh

Paginierte Liste von Belegen, die als Anhang an Buchungen hochgeladen wurden. Soft-gelöschte Belege sind standardmäßig ausgeblendet. Die Original-Datei (PDF/Bild) in S3 wird über diese API nicht bereitgestellt.

Hinweis: Dokumente aus der Belegerfassung (Upload mit OCR, Verbuchung erfolgt später) finden Sie unter /v1/gmbh/documents — dieser Endpoint hier liefert nur Buchungs-Anhänge.

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
kategoriestring (≤50)Belegkategorie (z. B. büromaterial, reisekosten).
fromdate (YYYY-MM-DD)Filter: beleg_datum ≥ from
todate (YYYY-MM-DD)Filter: beleg_datum ≤ to
include_deleted1 | omitBei '1' werden soft-gelöschte Belege mitgeliefert.
{
  "success": true,
  "data": [
    {
      "id": 812,
      "beleg_datum": "2026-04-10",
      "kategorie": "büromaterial",
      "beschreibung": "Toner HP LaserJet",
      "betrag": 129.00,
      "waehrung": "CHF",
      "file_type": "application/pdf",
      "file_size_bytes": 184320,
      "original_filename": "rechnung-toner.pdf",
      "buchung_id": null,
      "journal_entry_id": 4421,
      "asset_id": null,
      "is_deleted": false,
      "uploaded_at": "2026-04-10T08:44:11.000Z",
      "created_at": "2026-04-10T08:44:11.000Z",
      "updated_at": "2026-04-10T08:44:11.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/gmbh/belege/{id}

business_type = gmbh

Einzelner Beleg. Keine Original-Datei in der Response.

GET

/v1/gmbh/journal

business_type = gmbh

Paginierte Liste der Journal-Einträge (Hauptbuch). In der GmbH- Sektion ersetzt das Journal die einfache Buchungstabelle — jeder Eintrag repräsentiert eine doppelte Buchung mit Referenz auf das Geschäftsjahr.

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
fiscal_year_idintegerAuf ein Geschäftsjahr filtern.
statusenumdraft, posted, voided
sourcestring (≤30)Quelle der Buchung, z. B. invoice, bank_import, manual, payroll.
fromdate (YYYY-MM-DD)Filter: entry_date ≥ from
todate (YYYY-MM-DD)Filter: entry_date ≤ to
{
  "success": true,
  "data": [
    {
      "id": 4421,
      "fiscal_year_id": 15,
      "entry_number": "2026-00321",
      "entry_date": "2026-04-10",
      "description": "Toner HP — Bürobedarf",
      "reference": null,
      "source": "bank_import",
      "source_id": 9877,
      "status": "posted",
      "payment_method": "bank_transfer",
      "template_id": null,
      "voided_at": null,
      "void_reason": null,
      "created_at": "2026-04-10T08:44:12.000Z",
      "updated_at": "2026-04-10T08:44:12.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/gmbh/journal/{id}

business_type = gmbh

Einzelner Journal-Eintrag. Interne User-Referenzen (created_by, voided_by) werden nicht exponiert.

Referenzdaten (für Writes)

Diese Reads liefern die IDs, die Write-Endpoints benötigen (Konten, MWST-Sätze, offene Geschäftsjahre):

EndpointTypBeschreibung
GET /v1/gmbh/accountsreadKontenplan (paginiert). Filter: is_active, is_postable, account_type, search. Nur is_postable-Konten sind bebuchbar.
GET /v1/gmbh/vat-ratesreadMWST-Codes (Systemtabelle). Filter: active_on=YYYY-MM-DD.
GET /v1/gmbh/fiscal-yearsreadGeschäftsjahre inkl. eingebetteter aktiver Periodensperren (locked_periods).

Kontakte & Anlagen

EndpointTypBeschreibung
GET /v1/gmbh/debtors · GET /v1/gmbh/creditorsreadPaginierte Kontaktlisten. Filter: is_active, search.
GET /v1/gmbh/assetsreadAnlagenliste. Filter: status, category.
GET /v1/gmbh/assets/{id}/depreciation-schedulereadAbschreibungs-Vorschau (Jahresplan, linear/degressiv) — read-only.

Die zugehörigen POSTs sind unter Schreibzugriff dokumentiert.

Standard (Einzelunternehmen) Endpoints

Für Accounts ohne GmbH-Business-Type. Kein expliziter business_type-Check — jeder gültige Key darf zugreifen, die Daten sind aber user-scoped (kein Cross-Account- Leak).

GET

/v1/standard/invoices

Paginierte Liste von Rechnungen im Einzelunternehmen-Format.

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
statusstring (≤30)Rechnungsstatus (z. B. draft, sent, paid, overdue).
fromdate (YYYY-MM-DD)Filter: invoice_date ≥ from
todate (YYYY-MM-DD)Filter: invoice_date ≤ to
{
  "success": true,
  "data": [
    {
      "id": 88,
      "invoice_number": "2026-042",
      "invoice_date": "2026-04-10",
      "due_date": "2026-05-10",
      "customer": {
        "name": "Muster AG",
        "email": "[email protected]",
        "address": "Bahnhofstrasse 1",
        "zip": "8001",
        "city": "Zürich",
        "country": "CH",
        "vat_number": "CHE-123.456.789 MWST",
        "registration_code": null
      },
      "amount": 950.00,
      "net_amount": 881.59,
      "vat_amount": 68.41,
      "gross_amount": 950.00,
      "currency": "CHF",
      "vat_enabled": true,
      "status": "paid",
      "payment_method": "bank_transfer",
      "reference": null,
      "notes": null,
      "items": [ /* ... */ ],
      "booking_id": 512,
      "created_at": "2026-04-10T10:02:11.000Z",
      "updated_at": "2026-04-12T08:30:00.000Z",
      "uploaded_at": null
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/standard/invoices/{id}

Einzelne Rechnung. PDF-Binärdaten werden aus Bandbreiten- und Sicherheitsgründen nie in der Response geliefert.

GET

/v1/standard/belege

Paginierte Liste von Belegen. OCR-Rohtext und S3-Keys werden nicht exponiert.

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
fromdate (YYYY-MM-DD)Filter: beleg_datum ≥ from
todate (YYYY-MM-DD)Filter: beleg_datum ≤ to
{
  "success": true,
  "data": [
    {
      "id": 201,
      "beleg_datum": "2026-04-08",
      "beschreibung": "SBB Billet Zürich – Bern",
      "vendor_name": "SBB",
      "betrag": 51.00,
      "waehrung": "CHF",
      "vat_amount": 3.98,
      "vat_rate": 8.1,
      "mime_type": "image/jpeg",
      "file_size_bytes": 284112,
      "original_filename": "sbb-billet.jpg",
      "booking_id": 488,
      "processing_status": "done",
      "created_at": "2026-04-08T19:02:00.000Z",
      "updated_at": "2026-04-08T19:02:30.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/standard/belege/{id}

GET

/v1/standard/bookings

Paginierte Liste von Buchungen (einfache Kassenbuch-Einträge). Für GmbHs existiert stattdessen das Journal. Interne Matching-Felder (Bank-Fingerprint, Session-ID, presigned Receipt-URL) werden nicht exponiert.

Query-Parameter

ParameterTypDefaultBeschreibung
pageinteger1Siehe Pagination.
limitinteger (1–100)25Siehe Pagination.
typestring (≤30)Buchungstyp (z. B. income, expense).
statusstring (≤30)Status (z. B. confirmed, draft).
categorystring (≤50)Kategorie (z. B. bürokosten, honorar).
fromdate (YYYY-MM-DD)Filter: date ≥ from
todate (YYYY-MM-DD)Filter: date ≤ to
{
  "success": true,
  "data": [
    {
      "id": 488,
      "date": "2026-04-08",
      "amount": 51.00,
      "net_amount": 47.02,
      "vat_amount": 3.98,
      "vat_rate": 8.1,
      "vat_category": "normal",
      "currency": "CHF",
      "method": "card",
      "type": "expense",
      "status": "confirmed",
      "category": "reisekosten",
      "remark": "Kundentermin Bern",
      "invoice_id": null,
      "beleg_nummer": "B-201",
      "source": "manual",
      "created_at": "2026-04-08T19:02:00.000Z",
      "updated_at": "2026-04-08T19:02:00.000Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 1, "total_pages": 1, "has_next": false, "has_prev": false }
}
GET

/v1/standard/bookings/{id}

Einzelne Buchung inklusive MWST-Felder und Kategorie.

Kategorien & Kunden

EndpointTypBeschreibung
GET /v1/standard/categoriesreadBuchungskategorien (statisch). Filter: type (Einnahme | Ausgabe | Saldovortrag). Liefert die gültigen category-Werte für POST /v1/standard/bookings.
GET /v1/standard/customersreadPaginierte Kundenliste. Filter: search (Name/E-Mail/Ort).

Die zugehörigen POSTs sind unter Schreibzugriff dokumentiert.

Versionierung & Stabilität

Die API-Version ist im Pfad enthalten (/v1/). Breaking Changes erhalten eine neue Major-Version. Wir folgen dieser Policy:

  • Additiv = kein Breaking Change: Neue Felder in Responses, neue optionale Query-Parameter, neue Endpoints, neue Enum-Werte.
  • Breaking = neue Major-Version: Entfernen/ Umbenennen von Feldern, Pflicht-Parameter ändern, Typ-Wechsel, neue Auth-Anforderungen.
  • Deprecation: Deprecated Endpoints liefern zusätzlich einen Deprecation- und Sunset-Header (RFC 9745/8594). Mindestens 6 Monate Vorlauf.
  • Public Preview: Während v1 als Public Preview läuft, behalten wir uns geringfügige Änderungen an Response-Shapes vor. Breaking Changes werden im Changelog dokumentiert.

Sicherheit & Best Practices

  • Key wie Passwort behandeln. Nicht in öffentlichen Repos, Client-seitigem Code, Chat-Nachrichten oder Logs exponieren. Bei Push-to-Git mit versehentlichem Key gilt der Key als kompromittiert — sofort widerrufen.
  • Pro Integration ein Key. Kompromittierung eines Keys betrifft nicht Ihre anderen Integrationen und erlaubt gezieltes Widerrufen.
  • Sofortiger Widerruf. Verdachtsfall → Key in den Einstellungen widerrufen. Tritt sofort in Kraft (keine Cache-Verzögerung).
  • Nur HTTPS. Plain-HTTP-Requests werden abgewiesen. TLS 1.2 Minimum.
  • Server-to-Server. Keys gehören in ein Secrets-Management (Vault, 1Password, Doppler, DO App Platform Env-Vars). Niemals im Browser oder Mobile-App.
  • Logging. Masken Sie das Bearer-Token in eigenen Logs (nur pfs_live_*** zeigen).

Changelog

  • v1.2 — Juli 2026: Write-Endpoints (Entwürfe für GmbH-Journal inkl. /validate-Dry-Run, Rechnungen/Offerten, Standard- Buchungen/-Rechnungen, Debitoren/Kreditoren/Kunden, Anlagen, Beleg-Upload mit OCR) — abgesichert über Key-Scopes (leere Scopes = read-only), Idempotency-Key-Deduplizierung und strengere Write-Rate-Limits. Neue Referenz-Reads: Kontenplan, MWST-Codes, Geschäftsjahre + Periodensperren, Buchungskategorien, Kunden, Anlagen inkl. Abschreibungs-Vorschau. Neue Status-Codes 409/422. Additiv, kein Breaking Change.
  • v1.1 — Juni 2026: Neue Endpoints GET /v1/gmbh/documents und GET /v1/gmbh/documents/{id} — hochgeladene Dokumente (Belegerfassung mit OCR) inklusive noch nicht verbuchter Belege, mit Filtern processing_status und has_journal_entry. Additiv, kein Breaking Change.
  • v1.0 — April 2026: Erstveröffentlichung (Public Preview). Lesezugriff auf Rechnungen, Belege und Buchungen für GmbH und Einzelunternehmen. Bearer-Token-Auth, 120 req/min Rate Limit, paginierte JSON-Responses.

Roadmap

  • Reports lesen (Bilanz, Erfolgsrechnung, MWST-Report) für Agents
  • Bank-Import (CSV/CAMT) über die API
  • Webhooks: invoice.paid, beleg.created, journal.posted, …
  • Granulare Read-Scopes (read:invoices, …) — Writes sind bereits feingranular gescoped
  • OpenAPI 3.1 Spec + interaktiver Playground
  • SDK-Wrapper für TypeScript/Node, Python, PHP
Fehler in der Doku entdeckt? Schreiben Sie uns an [email protected].