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 > Öffnenoder 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.
- Interner Webserver - lokaler HTTP-Server zum Abruf einzelner Assets per URL, ideal für Integrationen mit anderen lokalen Tools.
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.logIn 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.
| Parameter | Typ | Bedeutung |
|---|---|---|
content | String (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
contentoder 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,
idusw.) 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).
Interner Webserver
Während Receipts Space läuft, startet im Hintergrund ein kleiner HTTP-Server, der ausschließlich auf localhost lauscht und somit nicht von außen erreichbar ist. Er dient dazu, einzelne Assets (z. B. das PDF eines Belegs) direkt per URL an andere lokale Tools, Skripte oder Browser zu übergeben, ohne den Umweg über temporäre Dateien.
Der Port wird beim Start dynamisch vom Betriebssystem vergeben und kann den Logfiles entnommen werden:
Server has started. Open at http://localhost:<port>/Der Port wird zudem beim JSON-Export als Präfix von url-Feldern in Asset-Referenzen verwendet.
Endpunkte
| Pfad | Bedeutung |
|---|---|
/ | Begrüßungsseite als einfache HTML-Antwort. |
/asset/<uid> | Liefert das (ggf. nachbearbeitete) Asset des Dokuments mit der angegebenen UID mit passendem MIME-Typ aus. |
/asset/<uid>?original | Liefert das Original-Asset (z. B. den unveränderten Scan vor OCR), sofern vorhanden. |
Die UID eines Dokuments ist identisch mit dem Feld id aus dem JSON-Import/-Export und kann auch über AppleScript abgefragt werden.
Hinweise:
- Es gibt keine Authentifizierung; die Bindung auf
localhostschützt vor Zugriffen aus dem Netzwerk. - Der Server läuft nur, solange die App geöffnet und die Bibliothek geladen ist. Nach dem Schließen der Library sind die URLs nicht mehr erreichbar.
- Die URLs sind nicht persistent - bei einem Neustart der App ändert sich der Port typischerweise. Für dauerhafte Referenzen bitte den JSON-Export mit eingebetteten Daten oder Dateipfaden nutzen.
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:
| Endung | Rolle | Bedeutung |
|---|---|---|
.receipts-import | Importer (JSON) | Explizite Endung für eine JSON-Datei im oben beschriebenen Format. Wird eindeutig als Import erkannt - ohne Verwechslungsgefahr mit anderen .json-Dateien. |
.receipts-package | Importer (Paket) | Importpaket als Bundle: kombiniert eine JSON-Beschreibung mit einer oder mehreren Asset-Dateien in einem einzigen, per Drag & Drop transportierbaren Container. |
.json | Importer (JSON) | Reguläre JSON-Datei. Wird geprüft und, wenn sie dem Dokumenten-Schema entspricht, importiert. |
.pdf | Importer | Wird als neues Dokument mit der PDF-Datei als Asset angelegt; Text wird extrahiert. |
.png, .jpg, .jpeg, .tif, .tiff, .gif | Importer | Bild wird als Asset importiert; bei aktivierter OCR wird zusätzlich der Text erkannt. |
.eml, .emlx | Importer | E-Mail-Datei; Anhänge werden als Belege importiert, der E-Mail-Text bleibt als Kontext erhalten. |
.xml | Viewer | Strukturierte 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.jpgInfo.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"
}
]
}filenameverweist auf eine Datei innerhalb vonFiles/.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 (ohnefilename), dann wird die URL direkt importiert.
Automatisches Aufräumen: Präfix ReceiptsMove-
Dateinamen, 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.pdfSchlä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
| Key | Typ | Bedeutung |
|---|---|---|
id | String | Eindeutige UID des Dokuments. Existiert sie bereits in der Bibliothek, wird das Dokument als Duplikat behandelt (siehe unten). Fehlt sie, wird eine neue UID vergeben. |
title | String | Titel des Dokuments. |
via | String | Quelle/Import-Kanal (z. B. "mail", "scan"). Wird andernfalls aus der Import-Session oder auf "json" gesetzt. |
reference | String | Referenznummer (Rechnungs-/Beleg-Nr.), wird auf das Feld name abgebildet. |
notes | String | Freitext-Notizen. |
text | String | Extrahierter 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. |
doctype | String | Dokumenttyp (intern; wird überschrieben, wenn isCredit = true). |
Flags
| Key | Typ | Bedeutung |
|---|---|---|
isConfirmed | Bool | “Bestätigt”-Flag. |
isMarked | Bool | Stern/Markierung. |
isCredit | Bool | Haben-Buchung. Setzt gleichzeitig doctype zurück. |
Datum
Datumsfelder akzeptieren entweder ein natives Date-Objekt oder einen ISO-8601-String.
| Key | Typ | Bedeutung |
|---|---|---|
date | ISO-Datum | Belegdatum. |
datePayment | ISO-Datum | Zahlungsdatum. |
dateAdded | ISO-Datum | Erstelldatum. 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) | Typ | Bedeutung |
|---|---|---|
currency | String (ISO 4217) | Originalwährung des Belegs. |
gross | Number/String | Bruttobetrag. Auf zwei Nachkommastellen gerundet. |
tax | Number/String | Gesamtsteuer (optional). |
taxDetails | Array | Einzelne Steuersätze. Entweder als Objekte { "percent": …, "value": … } oder als Tuple-Arrays [percent, value]. |
Key (unter amounts) | Typ | Bedeutung |
|---|---|---|
gross | Number/String | Bruttobetrag in der Default-Währung. Wird nur verwendet, wenn die Originalwährung von der Default-Währung abweicht. |
exchangeRate | Number/String | Explizit gesetzter Wechselkurs. Fehlt er, wird nach dem Import asynchron ein Kurs nachgeladen. |
Relationen
| Key | Typ | Bedeutung |
|---|---|---|
category | String oder Objekt | Kategorie. Als String (= Titel) oder Objekt { "id": "…", "title": "…" }. Bei id wird die existierende Kategorie per UID zugeordnet; sonst per Titel (wird ggf. neu angelegt). |
contact | String oder Objekt | Kontakt/Händler. Gleiches Format wie category. |
provider | String oder Objekt | Alias für contact, wird nur beim Import ausgewertet. |
tags | Array | Tags. Entweder ["Urlaub", "Reise"] oder [{ "title": "Urlaub" }, …]. |
IBAN
| Key | Typ | Bedeutung |
|---|---|---|
iban | String | IBAN. 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>"
}| Key | Typ | Bedeutung |
|---|---|---|
name | String | Dateiname (Default: "unnamed"). |
uti | String | Uniform Type Identifier. Wird verwendet, um den MIME-Typ abzuleiten, falls dieser fehlt. |
mime | String | MIME-Typ, überschreibt den aus uti abgeleiteten Wert. |
data | Data oder Base64-String | Direkte Binärdaten (bevorzugt). |
fileurl | String (URL) | Fallback 1: URL, von der die Daten gelesen werden. |
path | String | Fallback 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. |
url | String (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.
| Key | Typ | Default | Bedeutung |
|---|---|---|---|
onDuplicateSkip | Bool | false | Duplikat komplett überspringen, es erfolgt keine Aktualisierung. |
onDuplicateUnarchive | Bool | true | Archiviertes Duplikat wieder aus dem Papierkorb holen. |
onDuplicateFlag | Bool | true | Duplikat als solches markieren (Status-Code STATUS_CODE_DUPLICATE). |
onDuplicateIncludeKeys | Array<String> | - | Wenn gesetzt: nur diese Keys aus dem JSON werden angewendet; alle anderen ignoriert. |
onDuplicateExcludeKeys | Array<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",
}
}