Receipts
/v1/receiptsList receipts
The ledger's receipts, newest first: the app's receipt inbox. Filter
by status=parsed for the ones read but not yet on a transaction.
Parameters
limit integer · query | Page size, 1–200. |
cursor string | null · query | The next_cursor of the previous page. |
status string | null · query | Only receipts in this state: pending, parsed, attached, failed. |
transaction_id integer | null · query | Only receipts attached to this transaction. |
X-Organization-Id string | null · header |
Returns 200 · ReceiptList
data | |
has_more boolean · required | |
next_cursor string | null · required |
curl -X GET "https://api.lumaledger.app/v1/receipts" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"/v1/receiptsUpload a receipt
Upload a receipt as multipart/form-data and have it read. The
answer is the receipt as read (status attached, parsed or
failed), which takes a few seconds. Given a transaction_id it is put
on that transaction; otherwise it is attached only when one charge
clearly matches. The same file uploaded twice is one receipt
(already_here).
Parameters
Idempotency-Key string | null · header | Any unique string (a UUID is ideal). A retry with the same key returns the first attempt's response instead of doing the work twice. Keys are kept for 24 hours. |
X-Organization-Id string | null · header |
Body · multipart/form-data
file file · required | The receipt: a JPEG, PNG, WebP, GIF, HEIC or PDF, at most 10 MB. |
transaction_id integer | null | Attach it to this transaction instead of letting the matcher find one. |
Returns 201 · ReceiptUpload
already_here boolean · required | True when these exact bytes were already a receipt in this ledger: that receipt is returned and nothing new was made. |
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
curl -X POST "https://api.lumaledger.app/v1/receipts" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-F "file=@path/to/file"Try it isn't available for file uploads — use the curl example above.
/v1/receipts/{receipt_id}Delete a receipt
Delete a receipt and its file. If it was on a transaction, the split it made comes off too.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Returns 204 with no body.
curl -X DELETE "https://api.lumaledger.app/v1/receipts/{receipt_id}" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"/v1/receipts/{receipt_id}Get a receipt
One receipt with its line items and the transaction it is on.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Returns 200 · Receipt
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
curl -X GET "https://api.lumaledger.app/v1/receipts/{receipt_id}" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"/v1/receipts/{receipt_id}/attachAttach a receipt to a transaction
Put a receipt on the transaction it paid for, replacing any transaction it was on. Its line items become the transaction's split, scaled to what the card was actually charged.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Body · AttachRequest
transaction_id integer · required | The transaction the receipt paid for (see transactions.list). It must be an imported one: a bank or card charge. |
Returns 200 · Receipt
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
curl -X POST "https://api.lumaledger.app/v1/receipts/{receipt_id}/attach" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transaction_id": 1
}'/v1/receipts/{receipt_id}/detachDetach a receipt from its transaction
Take a receipt off its transaction, and its split with it. The
receipt stays, parsed, ready to attach elsewhere.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Returns 200 · Receipt
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
curl -X POST "https://api.lumaledger.app/v1/receipts/{receipt_id}/detach" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"/v1/receipts/{receipt_id}/downloadDownload a receipt's file
A short-lived URL for the receipt's image or PDF. A forwarded email that carried no receipt has no file, and says so with a 422.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Returns 200 · Download
expires_at datetime | null · required | When a signed url stops working. Null for a data: URL. |
url string · required | A signed HTTPS URL for the file, or a data: URL carrying the file itself when it is stored inline. Needs no credential. |
curl -X GET "https://api.lumaledger.app/v1/receipts/{receipt_id}/download" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"/v1/receipts/{receipt_id}/not-duplicateMark a receipt as not a duplicate
Two purchases, not one receipt sent twice: clear duplicate_of_id
and let the receipt find its own transaction.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Returns 200 · Receipt
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
curl -X POST "https://api.lumaledger.app/v1/receipts/{receipt_id}/not-duplicate" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"/v1/receipts/{receipt_id}/reprocessRead a receipt again
Read the file again from scratch, for a receipt that failed or was misread. It comes off its transaction first, and is placed again from the new reading.
Parameters
receipt_id integer · path · required | |
X-Organization-Id string | null · header |
Returns 200 · Receipt
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
curl -X POST "https://api.lumaledger.app/v1/receipts/{receipt_id}/reprocess" \
-H "Authorization: Bearer $LUMALEDGER_TOKEN"Objects
AttachRequest
Fields
transaction_id integer · required | The transaction the receipt paid for (see transactions.list). It must be an imported one: a bank or card charge. |
Download
Where to fetch a file. Fetch it promptly: the URL stops working at
expires_at, and asking again gives a fresh one.
Fields
expires_at datetime | null · required | When a signed url stops working. Null for a data: URL. |
url string · required | A signed HTTPS URL for the file, or a data: URL carrying the file itself when it is stored inline. Needs no credential. |
Money
An amount and its currency. `amount` is a base-10 string with two
decimal places and an optional leading minus sign. Parse it with a
decimal type, not a float.
Fields
amount string · required | Pattern: ^-?\d+\.\d{2}$. |
currency string · required | ISO 4217 code. Pattern: ^[A-Z]{3}$. |
Receipt
A receipt and what was read from it. Amounts are in the currency the
receipt was printed in (currency), which may not be the currency the
card was charged in.
Fields
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |
ReceiptEmail
Why a forwarded email yielded no receipt.
Fields
reason string | null · required | Machine value, e.g. no_attachment. |
snippet string | null · required | |
subject string | null · required |
ReceiptItem
One printed line of the receipt.
Fields
amount Money · required | |
category_id integer | null · required | The expense account this line is filed under once the receipt is attached (see accounts.list). |
description string · required | As printed. |
id integer · required | |
item_category string | null · required | A short label the reader gave the item, e.g. Produce. |
line_no integer · required | |
quantity string | null · required | Decimal string, when printed. |
unit_price |
ReceiptList
A page of receipts, newest first.
Fields
data | |
has_more boolean · required | |
next_cursor string | null · required |
ReceiptUpload
Fields
already_here boolean · required | True when these exact bytes were already a receipt in this ledger: that receipt is returned and nothing new was made. |
amount_before_tip | What the card terminal authorized before a tip was written in. |
attached_at datetime | null · required | |
card_last4 string | null · required | |
category_id integer | null · required | The expense account the reader suggested. |
created_at datetime · required | |
currency string · required | ISO 4217. The ledger's base currency until the receipt is read. |
duplicate_of_id integer | null · required | An older receipt this one appears to repeat. Clear it with receipts.mark_not_duplicate. |
email | Set when the row stands for a forwarded email, not a file. |
has_file boolean · required | False for a forwarded email that carried no receipt: there is nothing to download or re-read. |
id integer · required | |
items | |
match_confidence string | null · required | How sure the matcher was of the attachment, 0.00–1.00, as a decimal string. |
merchant_name string | null · required | |
mime_type string · required | |
notes string | null · required | |
original_name string | null · required | |
parse_error string | null · required | |
parsed_at datetime | null · required | |
payment_method string | null · required | |
receipt_date date | null · required | |
sender string | null · required | Who sent it in (an email address or phone number). |
size_bytes integer · required | |
source string · required | How it arrived: upload, email, whatsapp or gmail. |
stated_total | The total as printed, when total was worked out another way. |
status string · required | pending (not read yet), parsed (read, not on a transaction), attached (on a transaction) or failed (could not be read; see parse_error). |
subtotal | |
tax | |
tip | |
total | |
total_source string | null · required | Where total came from. |
transaction_id integer | null · required | The transaction it is attached to (see transactions.get). Null until it is attached, or while that transaction is not yet posted. |