Skip to main content

Understanding attachments in accounting systems

Most accounting systems let users attach supporting documents (PDFs, scanned images, receipts) to their bookkeeping records, typically on invoices (sales / purchase entries) and on journal entries (G/L entries). How those files are exposed varies a lot between connectors:
  • Some providers return a direct download URL for each attachment.
  • Others only signal that a document exists and require an additional API call to fetch the file content (returned as a base64-encoded string).
  • A few connectors cannot tell directly if an attachment exists. They return the status unknown.
With the Unified API, you don’t need to know which behaviour applies to which connector. Chift normalises everything behind a single attachments_info object and a single retrieval endpoint.

How Chift handles attachments

Every invoice and every journal entry returned by the Accounting API includes an attachments_info object that tells you what to expect:

Status values

Always inspect attachments_info.status first. Then either download the URL directly, call the Get attachments endpoint, or do nothing.

Retrieving invoice attachments

Invoices returned by the following endpoints include the attachments_info object:

1. When status is yes

The attachments array contains one or more entries with a direct URL. You can download the file straight from that URL. No additional API call is needed.

2. When status is yes_to_request

The attachments array may be empty. The status only signals that a file is available. To get the actual content, call the Get attachments endpoint with type=invoice:
The response returns a list of objects with the file as a base64-encoded string:
You can then decode base64_string on your end to reconstruct the original PDF or image file.
Connectors such as Odoo typically fall into the yes_to_request category for invoices.

Retrieving journal entry attachments

Journal entries follow the exact same pattern as invoices. The attachments_info object is available on: The only difference is the type query parameter you pass when status is yes_to_request. Use type=entry:
The response shape is identical to the invoice case: a list of objects with an id and a base64_string.