Schnittstellen / API

Receipts Space bietet mehrere Schnittstellen, um Belege und Dokumente automatisiert zu erzeugen, zu importieren, weiterzuverarbeiten und wieder zu exportieren.

Überblick

Import

  • Dateisystem - Dateien und Ordner per Drag & Drop, über Datei > Öffnen oder als Kommandozeilen-Parameter. Unterstützt werden PDF, Bilder (JPEG, PNG, HEIC …), E-Mails (EML) sowie JSON-Dateien im unten beschriebenen Format.
  • Ordnerüberwachung - einmalig konfigurierte Ordner (z. B. Scanner-Ausgabe oder iCloud-Ordner) werden dauerhaft beobachtet; neue Dateien werden automatisch importiert.
  • JSON-Import - strukturierter Import ganzer Dokumente inklusive Asset, Beträgen, Kategorien, Kontakten und Tags.
  • URL-Schema - Aufruf aus Browser, Mail oder Shortcuts über receipts-space://.... Ideal, um aus Web-Portalen direkt in die Library zu importieren.

Export

  • Drag & Drop / Zwischenablage - ausgewählte Dokumente lassen sich als PDF, als Originaldatei oder im JSON-Format (gleiches Schema wie der JSON-Import) in andere Apps übernehmen.
  • Datei > Exportieren - Stapel-Export in einen Ordner, inklusive optionaler Metadaten-Sidecars.
  • AppleScript export-Kommando - programmatischer Export einzelner oder gefilterter Dokumente. GitHub holtwick/receipts-api

Automatisierung

  • AppleScript - vollständige Automatisierung der App aus Skripten, Automator oder Shortcuts heraus. Das Terminologie-Lexikon ist direkt im Skripteditor von macOS einsehbar. Beispiele unter GitHub holtwick/receipts-api.
  • Direkter Bibliothekszugriff - die Bibliothek ist ein offenes Dokument-Bundle und kann von externen Tools gelesen und geschrieben werden. Details zum Aufbau stehen in der technischen Dokumentation und GitHub holtwick/receipts-space.

Bei Rückfragen hilft unser Support-Team gerne weiter.

Logfiles einsehen

Beim Arbeiten mit den Schnittstellen ist ein Blick ins Log oft der schnellste Weg zur Ursachenanalyse. Im Hauptmenü der App unter Hilfe:

  • Normal: Eintrag Support & Feedback - öffnet das Feedback-Formular.
  • Mit gedrückter ALT-Taste: Der Eintrag wechselt auf Open Log Files und öffnet den Log-Ordner im Finder.

Direkter Pfad:

~/Library/Logs/Receipts/de_holtwick_mac_homebrew_Receipts2.log

In der Mac-App-Store-Version weicht der Bundle-Identifier im Dateinamen leicht ab.

URL-Schema receipts-space://import

Importiert eine einzelne PDF-Datei, deren Binärdaten direkt in der URL übergeben werden. Aufrufbar aus Browser, Mail, Shortcuts oder beliebigen anderen Apps.

ParameterTypBedeutung
contentString (Base64-URL)Binärdaten des PDFs, kodiert nach RFC 4648 §5 (Base64-URL: -/_ statt +//, Padding = optional).

Beispiel:

receipts-space://import?content=JVBERi0xLjQKJeLjz9MKCg...

Hinweise:

  • Der Inhalt wird immer als PDF behandelt (UTI com.adobe.pdf). Andere Dateitypen werden von diesem Endpunkt derzeit nicht unterstützt - für Bilder, E-Mails oder strukturierte Daten bitte den JSON-Import oder eine Datei-basierte Übergabe verwenden.
  • Fehlt content oder lässt sich der Wert nicht dekodieren, wird der Aufruf stillschweigend verworfen.
  • Die Länge einer URL ist systembedingt begrenzt (typisch einige MB über open, deutlich weniger in Browsern). Für größere Dateien ist ein Datei-basierter Import stabiler.
  • Der Import läuft als manuelle Session durch die reguläre Import-Pipeline; Dublettenerkennung, Ordnerüberwachung etc. verhalten sich wie beim Datei-Import.
  • Weitere Metadaten (Titel, Kategorie, Beträge, id usw.) lassen sich über dieses Schema nicht mitgeben. Wer Metadaten setzen möchte, nutzt den JSON-Import (z. B. über eine .receipts-import-Datei oder ein .receipts-package).

Dateiendungen

Receipts Space registriert sich bei macOS für eine Reihe von Dateiendungen. Beim Öffnen einer solchen Datei (Doppelklick, Drag & Drop auf das App-Icon, open im Terminal) reagiert die App entsprechend der Endung. Hier die relevantesten:

EndungRolleBedeutung
.receipts-importImporter (JSON)Explizite Endung für eine JSON-Datei im oben beschriebenen Format. Wird eindeutig als Import erkannt - ohne Verwechslungsgefahr mit anderen .json-Dateien.
.receipts-packageImporter (Paket)Importpaket als Bundle: kombiniert eine JSON-Beschreibung mit einer oder mehreren Asset-Dateien in einem einzigen, per Drag & Drop transportierbaren Container.
.jsonImporter (JSON)Reguläre JSON-Datei. Wird geprüft und, wenn sie dem Dokumenten-Schema entspricht, importiert.
.pdfImporterWird als neues Dokument mit der PDF-Datei als Asset angelegt; Text wird extrahiert.
.png, .jpg, .jpeg, .tif, .tiff, .gifImporterBild wird als Asset importiert; bei aktivierter OCR wird zusätzlich der Text erkannt.
.eml, .emlxImporterE-Mail-Datei; Anhänge werden als Belege importiert, der E-Mail-Text bleibt als Kontext erhalten.
.xmlViewerStrukturierte XML-Daten (z. B. ZUGFeRD/X-Rechnung-Anhänge) werden geparst, soweit unterstützt.

Aufbau eines .receipts-package

Ein .receipts-package ist ein Ordner-Bundle mit folgendem Aufbau:

Meinpaket.receipts-package/
├── Info.json
└── Files/
    ├── rechnung-1.pdf
    └── scan-2.jpg

Info.json enthält das Manifest:

{
  "note": "Optionaler Hinweis, wird allen Dokumenten als Notiz angefügt.",
  "files": [
    {
      "filename": "rechnung-1.pdf",
      "title": "Hotelrechnung Berlin",
      "url": "https://example.com/invoice/42"
    },
    {
      "filename": "scan-2.jpg"
    }
  ]
}
  • filename verweist auf eine Datei innerhalb von Files/.
  • title (optional) wird als vorgeschlagener Titel übernommen, z. B. ein Seitentitel aus Safari.
  • url (optional) wird als Quell-URL im Dokument gespeichert; kann auch allein verwendet werden (ohne filename), dann wird die URL direkt importiert.

Automatisches Aufräumen: Präfix ReceiptsMove-

Datei­namen, die mit ReceiptsMove- beginnen, werden nach erfolgreichem Import automatisch in den Papierkorb verschoben. Gedacht war der Mechanismus ursprünglich für Mail.app-Temporärdateien, er funktioniert aber generisch:

ReceiptsMove-rechnung.pdf

Schlägt das Verschieben in den System-Papierkorb fehl (z. B. bei Netzlaufwerken), wird als Fallback ein Ordner .ReceiptsTrash neben der Datei angelegt und sie dort abgelegt.

JSON-Import in Receipts Space

Receipts Space kann Dokumente aus JSON-Dateien importieren. Dieses Dokument beschreibt das unterstützte Format und alle erkannten Felder.

Aufruf

Ein JSON-Import wird ausgelöst, sobald eine Datei mit UTI public.json an die App übergeben wird (Drag & Drop, Ordnerüberwachung, File > Open, AppleScript, URL-Schema usw.). Die Datei wird in import-from-url.swift erkannt und an den JSON-Importer in import-from-json.swift weitergereicht.

Die eigentliche Zuordnung der JSON-Felder auf ein DocumentSchema erfolgt in document-json-read.swift. Alle gültigen Schlüssel sind als Enum in document-json-keys.swift definiert.

Struktur der JSON-Datei

Die JSON-Datei enthält entweder ein einzelnes Dokument-Objekt oder ein Array von Dokument-Objekten. Arrays werden automatisch aufgespalten, jedes Element wird als eigenes Dokument importiert.

[
  { "id": "…", "title": "…",  },
  { "id": "…", "title": "…",  }
]

Felder

Identifikation

KeyTypBedeutung
idStringEindeutige UID des Dokuments. Existiert sie bereits in der Bibliothek, wird das Dokument als Duplikat behandelt (siehe unten). Fehlt sie, wird eine neue UID vergeben.
titleStringTitel des Dokuments.
viaStringQuelle/Import-Kanal (z. B. "mail", "scan"). Wird andernfalls aus der Import-Session oder auf "json" gesetzt.
referenceStringReferenznummer (Rechnungs-/Beleg-Nr.), wird auf das Feld name abgebildet.
notesStringFreitext-Notizen.
textStringExtrahierter Textinhalt des Dokuments (z. B. OCR-Ergebnis). Wird auch automatisch aus dem Asset extrahiert, wenn das Asset ein PDF ist und kein text mitgegeben wurde.
doctypeStringDokumenttyp (intern; wird überschrieben, wenn isCredit = true).

Flags

KeyTypBedeutung
isConfirmedBool“Bestätigt”-Flag.
isMarkedBoolStern/Markierung.
isCreditBoolHaben-Buchung. Setzt gleichzeitig doctype zurück.

Datum

Datumsfelder akzeptieren entweder ein natives Date-Objekt oder einen ISO-8601-String.

KeyTypBedeutung
dateISO-DatumBelegdatum.
datePaymentISO-DatumZahlungsdatum.
dateAddedISO-DatumErstelldatum. Wird bei Duplikaten ignoriert.

Beträge

Beträge werden in zwei Blöcken verwaltet: amountsOriginal (Originalwährung des Belegs) und amounts (umgerechnet in die Default-Währung der Bibliothek).

"amountsOriginal": {
  "currency": "USD",
  "gross": 123.45,
  "tax": 19.70,
  "taxDetails": [
    { "percent": 19, "value": 19.70 }
  ]
},
"amounts": {
  "gross": 115.12,
  "exchangeRate": 0.9325
}
Key (unter amountsOriginal)TypBedeutung
currencyString (ISO 4217)Originalwährung des Belegs.
grossNumber/StringBruttobetrag. Auf zwei Nachkommastellen gerundet.
taxNumber/StringGesamtsteuer (optional).
taxDetailsArrayEinzelne Steuersätze. Entweder als Objekte { "percent": …, "value": … } oder als Tuple-Arrays [percent, value].
Key (unter amounts)TypBedeutung
grossNumber/StringBruttobetrag in der Default-Währung. Wird nur verwendet, wenn die Originalwährung von der Default-Währung abweicht.
exchangeRateNumber/StringExplizit gesetzter Wechselkurs. Fehlt er, wird nach dem Import asynchron ein Kurs nachgeladen.

Relationen

KeyTypBedeutung
categoryString oder ObjektKategorie. Als String (= Titel) oder Objekt { "id": "…", "title": "…" }. Bei id wird die existierende Kategorie per UID zugeordnet; sonst per Titel (wird ggf. neu angelegt).
contactString oder ObjektKontakt/Händler. Gleiches Format wie category.
providerString oder ObjektAlias für contact, wird nur beim Import ausgewertet.
tagsArrayTags. Entweder ["Urlaub", "Reise"] oder [{ "title": "Urlaub" }, …].

IBAN

KeyTypBedeutung
ibanStringIBAN. E-Mail-artige Werte (enthalten @) werden ignoriert (Workaround für PayPal-Daten).

Assets (Dateianhang)

Das eigentliche Beleg-Dokument wird als asset angehängt, optional zusätzlich das Original unter assetOriginal (z. B. das unveränderte Scan-PDF vor OCR).

"asset": {
  "name": "rechnung.pdf",
  "uti": "com.adobe.pdf",
  "mime": "application/pdf",
  "data": "<base64>"
}
KeyTypBedeutung
nameStringDateiname (Default: "unnamed").
utiStringUniform Type Identifier. Wird verwendet, um den MIME-Typ abzuleiten, falls dieser fehlt.
mimeStringMIME-Typ, überschreibt den aus uti abgeleiteten Wert.
dataData oder Base64-StringDirekte Binärdaten (bevorzugt).
fileurlString (URL)Fallback 1: URL, von der die Daten gelesen werden.
pathStringFallback 2: Pfad zu einer lokalen Datei. Wird primär als absoluter Pfad interpretiert; kommt der JSON-Import aus einer Datei, wird zusätzlich relativ zu deren Ordner aufgelöst.
urlString (URL)Fallback 3: weitere URL-Quelle.

Die Quellen werden in der angegebenen Reihenfolge probiert; die erste, die nicht-leere Daten liefert, wird verwendet. Bei PDF-Assets wird zusätzlich der Textinhalt extrahiert, wenn text nicht bereits gesetzt ist.

Export/Import-Roundtrip

Der JSON-Export eines Dokuments (Drag & Drop, Zwischenablage, AppleScript export-Kommando) verwendet dasselbe Schema wie der Import und ist damit direkt wieder importierbar. Exportierte und importierte Felder teilen sich in der Implementierung das gleiche Schlüssel-Enum, so dass ein Roundtrip Export → Import die Daten verlustfrei zurückbringt. Assets werden beim Export wahlweise als url (interner Webserver), fileurl oder path referenziert; beim Import wird die erste verfügbare Quelle genutzt.

Bestehende Dokumente aktualisieren

Ein JSON-Import mit einer id, die bereits in der Bibliothek existiert, überschreibt die darin angegebenen Felder des vorhandenen Dokuments - es handelt sich also zugleich um eine Update-Schnittstelle. Nicht erwähnte Felder bleiben unverändert.

Standardmäßig wird das Dokument dabei als Duplikat markiert (Status “Duplikat” in der Liste). Für ein stilles Update ohne Markierung:

{
  "id": "…bestehende-uid…",
  "title": "Neuer Titel",
  "notes": "Ergänzte Notiz",
  "onDuplicateFlag": false
}

Mit onDuplicateIncludeKeys lässt sich das Update auf einzelne Felder beschränken; onDuplicateExcludeKeys bewirkt das Gegenteil. Details dazu im nächsten Abschnitt.

Duplikat-Handling

Ist bereits ein Dokument mit derselben id in der Bibliothek vorhanden, greift die Duplikat-Logik:

  • Dokument war endgültig gelöscht: wird wieder hergestellt und wie ein Neu-Import behandelt.
  • Dokument war im Papierkorb (archiviert): wird als Duplikat markiert. Verhalten steuerbar über folgende Keys.
KeyTypDefaultBedeutung
onDuplicateSkipBoolfalseDuplikat komplett überspringen, es erfolgt keine Aktualisierung.
onDuplicateUnarchiveBooltrueArchiviertes Duplikat wieder aus dem Papierkorb holen.
onDuplicateFlagBooltrueDuplikat als solches markieren (Status-Code STATUS_CODE_DUPLICATE).
onDuplicateIncludeKeysArray<String>-Wenn gesetzt: nur diese Keys aus dem JSON werden angewendet; alle anderen ignoriert.
onDuplicateExcludeKeysArray<String>-Diese Keys werden bei Duplikaten ignoriert.

Das Feld dateAdded wird bei Duplikaten nie übernommen, damit das ursprüngliche Anlage-Datum erhalten bleibt.

Beispiel

{
  "title": "Büromaterial",
  "via": "scan",
  "reference": "RE-2025-00123",
  "date": "2025-11-14",
  "datePayment": "2025-11-18",
  "isConfirmed": true,
  "amountsOriginal": {
    "currency": "EUR",
    "gross": 42.80,
    "taxDetails": [
      { "percent": 19, "value": 6.83 }
    ]
  },
  "category": "Büro",
  "contact": { "title": "Müller GmbH" },
  "tags": ["Q4", "Verbrauchsmaterial"],
  "iban": "DE89370400440532013000",
  "asset": {
    "path": "re-2025-00123.pdf",
  }
}