Interfaces / API

Receipts Space offers several interfaces to create, import, process, and export documents and receipts programmatically.

Overview

Import

  • File system - drag & drop files or folders, open them via File > Open, or pass them as command-line arguments. Supported formats include PDF, images (JPEG, PNG, HEIC …), e-mails (EML), and JSON files in the format described below.
  • Folder watching - configured folders (e.g. a scanner output folder or an iCloud folder) are watched permanently; new files are imported automatically.
  • JSON import - structured import of complete documents, including asset, amounts, categories, contacts, and tags.
  • URL scheme - invocation from a browser, mail client, or Shortcuts via receipts-space://.... Ideal for importing directly into the library from web portals.

Export

  • Drag & drop / clipboard - selected documents can be handed over to other apps as PDF, as the original file, or in JSON format (the same schema as the JSON import).
  • File > Export - batch export into a folder, with optional metadata sidecars.
  • AppleScript export command - programmatic export of individual or filtered documents. GitHub holtwick/receipts-api

Automation

  • AppleScript - full automation of the app from scripts, Automator, or Shortcuts. The terminology dictionary can be inspected directly in macOS Script Editor. Examples are available at GitHub holtwick/receipts-api.
  • Direct library access - the library is an open document bundle and can be read and written by external tools. Details on its structure are available in the technical documentation and GitHub holtwick/receipts-space.

If you have any further questions, our support team is happy to help.

Viewing Log Files

When working with these interfaces, the log is often the quickest way to diagnose issues. In the app’s main menu, under Help:

  • Normal: the item reads Support & Feedback - opens the feedback form.
  • With the Option (alt) key held down: the item switches to Open Log Files and reveals the log folder in Finder.

Direct path:

~/Library/Logs/Receipts/de_holtwick_mac_homebrew_Receipts2.log

In the Mac App Store edition, the bundle identifier in the filename differs slightly.

URL Scheme receipts-space://import

Imports a single PDF file whose binary data is passed directly inside the URL. Can be invoked from a browser, mail client, Shortcuts, or any other app.

ParameterTypeMeaning
contentString (Base64-URL)Binary data of the PDF, encoded as RFC 4648 §5 Base64-URL (-/_ instead of +//, padding = optional).

Example:

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

Notes:

  • The payload is always treated as PDF (UTI com.adobe.pdf). Other file types are not supported by this endpoint - for images, e-mails, or structured data, use the JSON import or a file-based hand-off instead.
  • If content is missing or cannot be decoded, the call is silently dropped.
  • URL length is limited by the host system (typically a few MB via open, considerably less in browsers). For larger files, a file-based import is more robust.
  • The import runs as a manual session through the regular import pipeline; duplicate detection, folder watching, etc. behave exactly as with a file import.
  • Additional metadata (title, category, amounts, id, …) cannot be supplied through this scheme. For metadata, use the JSON import (e.g. via a .receipts-import file or a .receipts-package).

File Extensions

Receipts Space registers itself with macOS for a number of file extensions. When such a file is opened (double click, drag & drop onto the app icon, open in Terminal), the app responds according to the extension. The most relevant ones:

ExtensionRoleMeaning
.receipts-importImporter (JSON)Explicit extension for a JSON file in the format described above. Recognized unambiguously as an import - no risk of confusion with other .json files.
.receipts-packageImporter (package)Import package as a bundle: combines a JSON description with one or more asset files in a single container that can be handled via drag & drop.
.jsonImporter (JSON)A regular JSON file. Inspected and, if it matches the document schema, imported.
.pdfImporterAdded as a new document with the PDF as its asset; text is extracted.
.png, .jpg, .jpeg, .tif, .tiff, .gifImporterThe image is imported as an asset; if OCR is enabled, the text is recognized as well.
.eml, .emlxImporterE-mail file; attachments are imported as receipts, the message body is retained as context.
.xmlViewerStructured XML data (e.g. ZUGFeRD / X-Rechnung attachments) is parsed where supported.

Structure of a .receipts-package

A .receipts-package is a folder bundle with the following layout:

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

Info.json contains the manifest:

{
  "note": "Optional note, attached to every document as its notes field.",
  "files": [
    {
      "filename": "invoice-1.pdf",
      "title": "Hotel invoice Berlin",
      "url": "https://example.com/invoice/42"
    },
    {
      "filename": "scan-2.jpg"
    }
  ]
}
  • filename refers to a file inside Files/.
  • title (optional) is used as the suggested title, e.g. a page title from Safari.
  • url (optional) is stored as the source URL on the document; may also be used on its own (without filename), in which case the URL is imported directly.

Auto-cleanup: ReceiptsMove- prefix

File names starting with ReceiptsMove- are moved to the trash automatically after a successful import. The mechanism was originally intended for Mail.app temporary files but works generically:

ReceiptsMove-invoice.pdf

If moving into the system trash fails (e.g. on network volumes), a fallback folder named .ReceiptsTrash is created next to the file and used instead.

JSON Import in Receipts Space

Receipts Space can import documents from JSON files. This section describes the supported format and all recognized fields.

Invocation

A JSON import is triggered as soon as a file with UTI public.json is passed to the app (drag & drop, folder watching, File > Open, AppleScript, URL scheme, etc.). The file is recognized in import-from-url.swift and forwarded to the JSON importer in import-from-json.swift.

The actual mapping of JSON fields onto a DocumentSchema happens in document-json-read.swift. All valid keys are defined as an enum in document-json-keys.swift.

Structure of the JSON File

The JSON file contains either a single document object or an array of document objects. Arrays are flattened automatically; each element is imported as its own document.

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

Fields

Identification

KeyTypeMeaning
idStringUnique UID of the document. If it already exists in the library, the document is treated as a duplicate (see below). If missing, a new UID is generated.
titleStringTitle of the document.
viaStringSource / import channel (e.g. "mail", "scan"). Otherwise taken from the import session or defaults to "json".
referenceStringReference number (invoice / receipt number), mapped to the name field.
notesStringFree-form notes.
textStringExtracted text content of the document (e.g. OCR result). Also extracted automatically from the asset if the asset is a PDF and text was not supplied.
doctypeStringDocument type (internal; overridden when isCredit = true).

Flags

KeyTypeMeaning
isConfirmedBool“Confirmed” flag.
isMarkedBoolStar / flag.
isCreditBoolCredit entry. Also resets doctype.

Dates

Date fields accept either a native date object or an ISO 8601 string.

KeyTypeMeaning
dateISO dateDocument date.
datePaymentISO datePayment date.
dateAddedISO dateCreation date. Ignored for duplicates.

Amounts

Amounts are stored in two blocks: amountsOriginal (the original currency of the receipt) and amounts (converted into the library’s default currency).

"amountsOriginal": {
  "currency": "USD",
  "gross": 123.45,
  "tax": 19.70,
  "taxDetails": [
    { "percent": 19, "value": 19.70 }
  ]
},
"amounts": {
  "gross": 115.12,
  "exchangeRate": 0.9325
}
Key (inside amountsOriginal)TypeMeaning
currencyString (ISO 4217)Original currency of the receipt.
grossNumber/StringGross amount. Rounded to two decimal places.
taxNumber/StringTotal tax (optional).
taxDetailsArrayIndividual tax rates. Either as objects { "percent": …, "value": … } or as tuple arrays [percent, value].
Key (inside amounts)TypeMeaning
grossNumber/StringGross amount in the default currency. Only used when the original currency differs from the default.
exchangeRateNumber/StringExplicit exchange rate. If missing, a rate is fetched asynchronously after import.

Relations

KeyTypeMeaning
categoryString or objectCategory. Either as a string (= title) or as an object { "id": "…", "title": "…" }. With id, an existing category is matched by UID; otherwise by title (a new one is created if necessary).
contactString or objectContact / merchant. Same format as category.
providerString or objectAlias for contact, recognized only on import.
tagsArrayTags. Either ["Travel", "Vacation"] or [{ "title": "Travel" }, …].

IBAN

KeyTypeMeaning
ibanStringIBAN. E-mail-like values (containing @) are ignored (workaround for PayPal data).

Assets (File Attachment)

The actual receipt document is attached as asset, optionally with the untouched original under assetOriginal (e.g. the unmodified scan PDF before OCR).

"asset": {
  "name": "invoice.pdf",
  "uti": "com.adobe.pdf",
  "mime": "application/pdf",
  "data": "<base64>"
}
KeyTypeMeaning
nameStringFile name (default: "unnamed").
utiStringUniform Type Identifier. Used to derive the MIME type if that is missing.
mimeStringMIME type; overrides the value derived from uti.
dataData or Base64 stringDirect binary data (preferred).
fileurlString (URL)Fallback 1: URL the data is read from.
pathStringFallback 2: path to a local file. Interpreted as an absolute path first; when the JSON import comes from a file, the path is also resolved relative to that file’s directory.
urlString (URL)Fallback 3: additional URL source.

The sources are tried in the order shown; the first one that yields non-empty data is used. For PDF assets, the text content is also extracted unless text has already been set.

Export/Import Round-trip

The JSON export of a document (drag & drop, clipboard, AppleScript export command) uses the same schema as the import and can be fed straight back in. Exported and imported fields share the same key enum internally, so an export → import round-trip brings the data back without loss. Assets on export are referenced either as url (internal web server), fileurl, or path; on import the first available source is used.

Updating Existing Documents

A JSON import with an id that already exists in the library overwrites the given fields on the existing document - the endpoint doubles as an update interface. Fields not mentioned remain unchanged.

By default the document is marked as a duplicate (status “Duplicate” in the list). For a silent update without that marker:

{
  "id": "…existing-uid…",
  "title": "New title",
  "notes": "Amended note",
  "onDuplicateFlag": false
}

onDuplicateIncludeKeys limits the update to specific fields; onDuplicateExcludeKeys does the opposite. Details in the next section.

Duplicate Handling

If a document with the same id already exists in the library, the duplicate logic kicks in:

  • Document was permanently deleted: it is restored and treated as a new import.
  • Document was in the trash (archived): it is marked as a duplicate. Behavior is controlled by the keys below.
KeyTypeDefaultMeaning
onDuplicateSkipBoolfalseSkip the duplicate entirely; no update is performed.
onDuplicateUnarchiveBooltrueBring an archived duplicate back out of the trash.
onDuplicateFlagBooltrueMark the duplicate as such (status code STATUS_CODE_DUPLICATE).
onDuplicateIncludeKeysArray<String>-If set: only these keys from the JSON are applied; all others are ignored.
onDuplicateExcludeKeysArray<String>-These keys are ignored for duplicates.

The dateAdded field is never applied to duplicates, to preserve the original creation date.

Example

{
  "title": "Office supplies",
  "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": "Office",
  "contact": { "title": "Müller GmbH" },
  "tags": ["Q4", "Consumables"],
  "iban": "DE89370400440532013000",
  "asset": {
    "path": "re-2025-00123.pdf",    
  }
}