Work with files and attachments
Upload files, attach them to accounting records, retrieve their metadata, and manage their lifecycle safely.
Work with files and attachments
Upload supporting documents to Wafeq once, then attach the returned file ID to the accounting records that need them.
Typical examples include receipts, supplier invoices, contracts, purchase-order documents, customer evidence, and journal support.
How files and attachments relate
A file and an attachment are two parts of the same workflow:
- Upload the binary data through the Files API.
- Store the returned Wafeq file id.
- Put that ID in a record's attachments array.
- Retrieve the accounting record to confirm the relationship.
The file object stores the content and metadata. The accounting record stores only the relationship to the file ID.
Records that support attachments
The current API schema exposes attachments on:
- Contacts
- Quotes
- Invoices and credit notes
- Purchase orders
- Bills and debit notes
- Expenses
- Manual journals
- Payment requests
- Projects
The field is an array, so a record can reference more than one file.
Upload with multipart form data
Use Create file for the most common upload flow:
curl --request POST "https://api.wafeq.com/v1/files/" \
--header "Authorization: Api-Key <API_KEY>" \
--form "[email protected]"A successful 201 response includes:
| Field | Meaning |
|---|---|
| id | File ID to place in an attachments array |
| file | URI for the stored file content |
| original_filename | Original name supplied during upload |
| mime_type | Detected or stored media type |
| file_size | File size in bytes |
| created_ts and modified_ts | File timestamps in UTC |
Persist the file ID next to the source document in your integration.
Upload raw binary content
Use Create file (advance) when your service already has the binary body and does not need multipart encoding.
The request must include a Content-Disposition header with the filename:
curl --request POST "https://api.wafeq.com/v1/files/raw/" \
--header "Authorization: Api-Key <API_KEY>" \
--header "Content-Type: application/pdf" \
--header 'Content-Disposition: attachment; filename="receipt.pdf"' \
--data-binary "@receipt.pdf"Use the real MIME type of the content. Do not send every upload as a generic binary type when your application knows the correct type.
Attach a file when creating a record
Pass one or more returned file IDs in attachments:
{
"account": "<EXPENSE_ACCOUNT_ID>",
"paid_through_account": "<CARD_ACCOUNT_ID>",
"amount": 315,
"currency": "AED",
"date": "2026-08-29",
"description": "Team travel",
"attachments": [
"<RECEIPT_FILE_ID>",
"<APPROVAL_FILE_ID>"
]
}The same pattern applies to other supported objects. Check the target endpoint's schema before sending the field.
Add or remove attachments later
Update the accounting record through its PATCH endpoint.
Treat attachments as the complete desired set when updating: retrieve the current record, add or remove IDs in your application, then send the full array you intend the record to retain.
curl --request PATCH "https://api.wafeq.com/v1/expenses/<EXPENSE_ID>/" \
--header "Authorization: Api-Key <API_KEY>" \
--header "Content-Type: application/json" \
--data '{
"attachments": [
"<EXISTING_FILE_ID>",
"<NEW_FILE_ID>"
]
}'Removing a file ID from a record and deleting the underlying file are separate operations.
List and retrieve files
Use List files to page through uploaded files:
curl "https://api.wafeq.com/v1/files/?mime_type=application%2Fpdf&page_size=100" \
--header "Authorization: Api-Key <API_KEY>"Available filters include:
- Creation and modification timestamp ranges
- MIME type
- Original filename
- Minimum and maximum file size
- Page and page size
Use Retrieve file when you already have the file ID.
Delete files safely
Use Delete file only after confirming that no active accounting record should retain it:
curl --request DELETE "https://api.wafeq.com/v1/files/<FILE_ID>/" \
--header "Authorization: Api-Key <API_KEY>" \
--header "X-Wafeq-Idempotency-Key: delete-file-<FILE_ID>"Before deletion:
- Find the source-system mapping for the file.
- Remove the ID from records that should no longer reference it.
- Confirm your retention and audit requirements.
- Delete the file.
- Remove the local mapping only after the API succeeds.
Production guidance
- Allow only the file types and sizes your product expects.
- Preserve the original filename and source record ID in your own mapping.
- Do not log file contents, API keys, or private file URIs.
- Do not infer storage URLs; use the URI returned by Wafeq.
- File upload endpoints do not currently expose the idempotency header in the API schema. Track upload attempts and returned IDs so a timeout does not create uncontrolled duplicates.
- Keep file retention aligned with the accounting document's legal and audit requirements.
For a receipt-based workflow, continue with Record expenses and receipts.
Updated about 2 hours ago