When an expense nature requires a receipt (i.e. the receipt is mandatory), you must follow a three-step process to attach it. You cannot pass a file upload ID directly in the expenseReceipts array — doing so will result in a 403 Forbidden error.
Step 1 — Upload the file
First, upload the receipt file (image, PDF, etc.) using the Files API :
Upload a file
Response (201 Created)
POST /lucca-files/api/uploads HTTP/2
Host : example.ilucca.net
Authorization : lucca application={API_KEY}
Accept : application/json
Content-Type : multipart/form-data; boundary=----FormBoundary
------FormBoundary
Content-Disposition : form-data; name="form"; filename="receipt.pdf"
Content-Type : application/pdf
< ./receipt.pdf
------FormBoundary--
Save the returned id — this is your uploadId for the next step.
Step 2 — Create an ExpenseReceipt
Next, create an ExpenseReceipt resource by calling POST /api/v3/expenseReceipts. This step links the uploaded file to the Expenses module:
Create an ExpenseReceipt
Response (200 OK)
POST /api/v3/expenseReceipts HTTP/2
Host : example.ilucca.net
Authorization : lucca application={API_KEY}
Content-Type : application/json
{
"ownerId" : 123 ,
"requiresOcr" : false ,
"sourceId" : "WebForm" ,
"uploadId" : "a24f4279-6bb4-4e1c-9b40-a80a5d44b36d"
}
Property Type Description ownerIdintegerThe user ID of the expense owner. Must match the owner of the expense you will create at the next step. requiresOcrbooleanSet to true if you want Lucca to run OCR (optical character recognition) on the receipt to automatically extract data. sourceIdstringThe source of the receipt. Use "WebForm" when creating via API. uploadIdstring (uuid)The id returned by /lucca-files/api/uploads in step 1.
Save the returned id (here f0d01fd0-...) — this is the ExpenseReceipt ID you will reference in the expense.
Step 3 — Create the expense with the receipt attached
Finally, create the expense via POST /api/v3/expenseTempItems, referencing the ExpenseReceipt by its id:
Create expense with receipt
POST /api/v3/expenseTempItems HTTP/2
Host : example.ilucca.net
Authorization : lucca application={API_KEY}
Content-Type : application/json
{
"expenseNatureId" : 1 ,
"purchasedOn" : "2025-06-15" ,
"paymentMethodId" : 0 ,
"quantity" : 1 ,
"originalTransaction" : {
"currencyId" : "EUR" ,
"grossAmount" : 42.50
},
"processedAmounts" : {
"grossAmount" : 42.50 ,
"currencyId" : "EUR"
},
"deviceId" : "Web" ,
"ownerId" : 123 ,
"merchant" : "Restaurant ABC" ,
"comment" : "Business lunch" ,
"expenseReceipts" : [
{ "id" : "f0d01fd0-5f27-4061-8dca-bee6318b0103" }
]
}
Do not pass the file upload ID (from step 1) directly in expenseReceipts. You must create an ExpenseReceipt resource first (step 2) and reference that ID. Passing the upload ID directly will result in a 403 Forbidden error with the message: “Property Id of type CleemyFile is not writable” .
Summary