---
updatedAt: 2026-08-28T22:37:42.000Z
agentTools:
  projectIndex: https://developer.wafeq.com/llms.txt
---

# Record expenses and receipts

Capture operational spend, attach receipt files, and post expenses to the ledger with the right account and dimensions.

# Record expenses and receipts

Use expenses for purchases paid at the time of the transaction—for example card spend, petty cash, and employee-paid operating costs. Use bills when the supplier must be paid later.

## Prepare the accounting context

Resolve these IDs before creating the expense:

* **account**: where the expense appears in the chart of accounts.
* **paid\_through\_account**: the bank, card, cash, or clearing account used to pay.
* **tax\_rate**: the tax treatment, when applicable.
* **contact**: the merchant or supplier, when useful.
* **project**, **cost\_center**, and **branch**: optional reporting dimensions.

Use [List accounts](/reference/accounts_list) with **is\_payment\_enabled=true** to find eligible payment accounts.

## Upload receipt files

Create the supporting document with [Create file](/reference/upload_file), then place the returned file ID in the expense **attachments** array. Keep the original filename and source-system reference so finance users can trace the evidence.

See [Work with files and attachments](/docs/work-with-files-and-attachments) for multipart and raw uploads, file metadata, later updates, and safe deletion.

## Create the expense

```bash
curl --request POST "https://api.wafeq.com/v1/expenses/" \
  --header "Authorization: Api-Key <API_KEY>" \
  --header "Content-Type: application/json" \
  --header "X-Wafeq-Idempotency-Key: expense-<SOURCE_ID>" \
  --data '{
    "account": "<EXPENSE_ACCOUNT_ID>",
    "paid_through_account": "<CARD_OR_CASH_ACCOUNT_ID>",
    "amount": 315,
    "currency": "AED",
    "date": "2026-08-29",
    "description": "Team travel",
    "reference": "TRIP-882",
    "external_id": "expense_882",
    "tax_amount_type": "TAX_INCLUSIVE",
    "tax_rate": "<TAX_RATE_ID>",
    "contact": "<MERCHANT_CONTACT_ID>",
    "project": "<PROJECT_ID>",
    "cost_center": "<COST_CENTER_ID>",
    "attachments": ["<FILE_ID>"]
  }'
```

The returned **status** shows whether the expense is a draft or has posted to the ledger.

## Draft and posted states

Use [Mark expense as posted](/reference/expenses_mark_as_posted_create) when review is complete:

```bash
curl --request POST "https://api.wafeq.com/v1/expenses/<EXPENSE_ID>/mark-as-posted/" \
  --header "Authorization: Api-Key <API_KEY>" \
  --header "Content-Type: application/json"
```

Use [Mark expense as draft](/reference/expenses_mark_as_draft_create) only when the accounting workflow permits the record to return to draft.

## Avoid duplicate spend

Use both controls:

* **external\_id** maps the Wafeq expense to the durable ID in your source system.
* **X-Wafeq-Idempotency-Key** makes retries of the same create request safe.

Do not generate a new idempotency key when retrying a timed-out request for the same expense.

## Expense or bill?

| Situation                                           | Record                    |
| --------------------------------------------------- | ------------------------- |
| Paid immediately by card, cash, or clearing account | Expense                   |
| Supplier invoice is due later                       | Bill                      |
| Procurement approval precedes the supplier invoice  | Purchase order, then bill |

For payable workflows, continue with [Purchase to pay](/docs/purchase-to-pay).