> ## Documentation Index
> Fetch the complete documentation index at: https://developer.findity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fields - Receipt expenses

Create and manage receipt-based expenses using the dynamic Fields system in the Expense API.

Create receipt-based expenses using the dynamic Fields system. This guide covers uploading receipts with OCR, initializing fields, handling categories and tax, managing representation expenses, and saving.

## Overview

Receipt expenses use the `ReceiptVerification` expense type. They represent standard purchases where a user submits a receipt for reimbursement — covering everything from office supplies and meals to travel costs and representation/entertainment.

This is the most common expense type and has the most straightforward field structure, making it the recommended starting point for your Fields integration. The server handles tax calculations, VAT logic, and country-specific rules — your client renders the fields and lets the user fill them in.

## Key concepts

| Concept | Description |
| - | - |
| **OCR scanning** | Upload a receipt image before creating the expense. The API extracts amount, tax, currency, date, and suggests categories — pre-filling the form. |
| **Categories** | Each organization defines expense categories (e.g., Travel, Meals, Office supplies). Changing the category can alter which fields are visible. |
| **Tax / VAT** | Tax fields are calculated server-side based on category, country, and amount. Your client displays them but doesn't compute them. |
| **Representation** | Entertainment/representation expenses have additional fields: guest lists, purpose, and representation type. These appear dynamically when the category requires it. |
| **Content** | Receipt images and PDF attachments are uploaded separately via the Content API and referenced by ID in the fields. |

## API endpoints

| Operation | Method | Endpoint |
| - | - | - |
| Upload receipt (with OCR) | `POST` | `/v1/expense/content?action=scan&organizationId={id}` |
| Upload receipt (without OCR) | `POST` | `/v1/expense/content?organizationId={id}` |
| Initialize fields | `GET` | `/v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/fields` |
| Update fields | `PUT` | `/v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/fields` |
| Create expense | `POST` | `/v1/expense/expenses?format=fields&organizationId={id}&expenseType=ReceiptVerification` |
| Update expense | `PUT` | `/v1/expense/expenses/{expenseId}?format=fields` |
| Get categories | `GET` | `/v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/categories` |
| Get currencies | `GET` | `/v1/expense/me/organizations/{id}/currencies` |
| Get payment types | `GET` | `/v1/expense/me/organizations/{id}/paymenttypes` |
| Retrieve receipt image | `GET` | `/v1/expense/content/{id}/image?size={width}x{height}` |

## Step 1: Upload the receipt

Upload the receipt image before initializing fields. Use `action=scan` to trigger OCR, which extracts data that can pre-fill the expense form.

```bash bash theme={"system"}
curl -X POST "https://stage-api.findity.com/api/v1/expense/content?action=scan&organizationId={orgId}" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: image/jpeg" \
  -H "Content-Name: receipt.jpg" \
  --data-binary @receipt.jpg
```

### Example response

```json theme={"system"}
{
  "id": "ff808181826e28b201826e56fc980005",
  "name": "receipt.jpg",
  "contentType": "image/jpeg",
  "scanResult": {
    "id": "ff808181826e28b201826e5700e30006",
    "amount": 350.00,
    "taxAmount": 70.00,
    "currency": "SEK",
    "purchaseDate": "2024-03-15T00:00:00Z",
    "categoryIds": [
      "a1b2c3d4e5f6",
      "b2c3d4e5f6a1"
    ],
    "categoryId": "a1b2c3d4e5f6"
  }
}
```

### Scan result fields

| Field | Type | Description |
| - | - | - |
| `id` | string | Scan result ID — pass to fields initialization and category lookup |
| `amount` | number | Extracted total amount |
| `taxAmount` | number | Extracted tax/VAT amount |
| `currency` | string | Detected currency code |
| `purchaseDate` | string | Detected purchase date (ISO 8601) |
| `categoryIds` | string\[] | Up to 3 suggested category IDs, ordered by confidence |
| `categoryId` | string | Top suggested category ID (convenience shorthand for `categoryIds[0]`) |

> [!NOTE]
>
> Not all fields are guaranteed in a scan result — OCR accuracy depends on receipt quality. Always let the user review and correct pre-filled values.

## Step 2: Initialize fields

Fetch the field structure for a new receipt expense:

```bash bash theme={"system"}
curl -X GET "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/ReceiptVerification/fields" \
  -H "Authorization: Bearer {access_token}"
```

To apply scan results, first initialize the fields with GET, then apply the scan result via PUT:

```bash bash theme={"system"}
curl -X PUT "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/ReceiptVerification/fields?applyScanResult={scanResultId}" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{ "fields": [...fields from GET response...] }'
```

To load an existing expense for editing:

```bash bash theme={"system"}
curl -X GET "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/ReceiptVerification/fields?expenseRecordId={expenseId}" \
  -H "Authorization: Bearer {access_token}"
```

### Field structure overview

The response contains these key fields:

| Field property | controlType | Description |
| - | - | - |
| `id` | `TEXT` | Expense ID (hidden, system field) |
| `categoryId` | `LIST` | Expense category — `requiresUpdate: true` |
| `verification.comment` | `MULTI_LINE_TEXT` | User comment |
| `verification.description` | `TEXT` | Expense description |
| `expenseReportId` | `LIST` | Assign to an expense report |
| `verification.receiptAttachment` | `CONTENT_HOLDER` | Receipt image or PDF attachment |
| `verification.purchaseDate` | `DATE` | Date of purchase — `requiresUpdate: true` |
| `verification.currencyCode` | `LIST` | Transaction currency — `requiresUpdate: true` |
| `verification.totalAmount` | `DOUBLE` | Total amount including tax (shown as "Amount incl. VAT") |
| `verification.taxAmount` | `DOUBLE` | Tax / VAT amount |
| `verification.paymentTypeId` | `LIST` | Payment method (cash, corporate card, etc.) |
| `verification.verificationNumber` | `TEXT` | System-generated verification number (read-only) |
| `verification.storeName` | `TEXT` | Store or merchant name |
| `verification.exchangeRate` | `DOUBLE` | Exchange rate (appears when foreign currency selected) |
| Custom dimension fields | `LIST` | Organization-specific dimensions (e.g., cost center, project) |

## Step 3: Handle categories and tax

The category field (`categoryId`) has `requiresUpdate: true`. Changing the category triggers a server round-trip that can:

* Show or hide tax fields based on the category's tax rules
* Reveal representation fields (guest list, purpose) for entertainment categories
* Change which custom dimensions are visible
* Update VAT calculation logic

### Fetching categories

```
GET /v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/categories
```

### Example response

```json theme={"system"}
{
  "meta": { "count": 5, "total": 5 },
  "data": [
    {
      "id": "a1b2c3d4e5f6",
      "name": "Travel",
      "iconUrl": "https://expense.findity.com/api/resources/...",
      "section": "Common"
    },
    {
      "id": "b2c3d4e5f6a1",
      "name": "Meals & Entertainment",
      "iconUrl": "https://expense.findity.com/api/resources/...",
      "section": "Representation"
    }
  ]
}
```

Categories may include a `section` property for grouping in the UI.

### Category suggestions from scan

If you used OCR scanning in Step 1, pass the `scanResultId` when fetching categories to highlight 0–3 suggested categories in the picker:

```
GET /v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/categories?scanResultId={scanResultId}
```

Suggested categories are returned with a `suggested: true` flag. Display them prominently so the user can quickly confirm or change the pre-selected category.

### Tax fields

Tax-related fields appear based on the selected category and country. Common tax fields include:

| Field property | controlType | Description |
| - | - | - |
| `verification.taxAmount` | `DOUBLE` | Tax / VAT amount — may be auto-calculated |
| `verification.nonDeductibleVat` | `DOUBLE` | Non-deductible VAT portion |
| `verification.taxPercentage` | `LIST` | Tax rate selector (where applicable) |

> [!NOTE]
>
> Tax fields are computed server-side. When the user changes `totalAmount`, `currencyCode`, or `categoryId`, send a PUT to get recalculated tax values. Never compute tax client-side — rules vary by country, category, and organization settings.

## Step 4: Handle currency and exchange rates

When a user selects a foreign currency (different from the organization's reimbursement currency), additional exchange rate fields appear:

| Field property | controlType | Description |
| - | - | - |
| `verification.currencyCode` | `LIST` | Transaction currency — `requiresUpdate: true` |
| `verification.exchangeRate` | `DOUBLE` | Exchange rate to reimbursement currency |

The `currencyCode` field has `requiresUpdate: true` — changing it triggers a server round-trip that fetches the current exchange rate. The reimbursement amount is calculated at the expense record level (not within the verification object) and returned as `reimbursementAmount` on the expense itself.

### Fetching currencies

```
GET /v1/expense/me/organizations/{id}/currencies
```

Returns the list of currencies available in the organization. The `data` property on the `currencyCode` field contains the currently selected currency.

## Step 5: Handle representation expenses

When a category requires representation/entertainment details, additional fields appear dynamically after the category is selected:

| Field property | controlType | Description |
| - | - | - |
| `verification.representation.type` | `LIST` | Type of representation (internal, external, etc.) — `requiresUpdate: true` |
| `verification.representation.guests` | `GUEST_LIST` | List of guests with name and company |
| `verification.representation.numberOfGuests` | `INTEGER` | Total number of guests |
| `verification.representation.numberOfExternalGuests` | `INTEGER` | Number of external guests |
| `verification.representation.place` | `TEXT` | Place or venue name |
| `verification.representation.includesLiquor` | `SWITCH` | Whether liquor/wine/strong beer was included |
| `verification.representation.guestListAttached` | `SWITCH` | Whether to attach a guest list file — `requiresUpdate: true` |
| `verification.representation.guestListAttachment` | `CONTENT_HOLDER` | Attached guest list PDF or document |

### Guest list format

The `GUEST_LIST` control type holds an array of guest objects:

```json theme={"system"}
[
  { "name": "Jane Smith", "company": "Acme Corp" },
  { "name": "John Doe", "company": "Example Ltd" }
]
```

### Representation types

Fetch representation types for the selected category:

```
GET /v1/expense/me/organizations/{id}/representationtypes
```

The `verification.representation.type` field has `requiresUpdate: true` — changing it may alter visibility of other representation fields based on the organization's configuration.

## Step 6: The update cycle

Receipt expenses have several fields with `requiresUpdate: true`. When the user changes any of these, send the full fields array back to the server:

```
PUT /v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/fields
```

Fields that trigger an update:

| Field | What changes on update |
| - | - |
| `categoryId` | Tax rules, visible dimensions, representation fields, VAT logic |
| `verification.currencyCode` | Exchange rate, reimbursement amount |
| `verification.totalAmount` | Tax recalculation (in some configurations) |
| `verification.representation.type` | Representation field visibility |
| `verification.paymentTypeId` | Reimbursement-related fields |

### Example update request

```bash bash theme={"system"}
curl -X PUT "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/ReceiptVerification/fields" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      { "property": "id", "value": null },
      { "property": "categoryId", "value": "a1b2c3d4e5f6" },
      { "property": "verification.receiptAttachment", "value": "ff808181826e28b201826e56fc980005" },
      { "property": "verification.purchaseDate", "value": "2024-03-15T00:00:00Z" },
      { "property": "verification.currencyCode", "value": "SEK" },
      { "property": "verification.totalAmount", "value": 350.00 },
      { "property": "verification.taxAmount", "value": 70.00 },
      { "property": "verification.paymentTypeId", "value": "CASH" },
      { "property": "verification.comment", "value": "Office supplies for Q1 planning" }
    ]
  }'
```

> [!WARNING]
>
> Always send the complete fields array — including hidden fields and fields you didn't modify. The server uses the full state to compute the response.

## Step 7: Save the expense

Once the user has filled in all required fields, save the receipt expense.

### Using fields format (recommended)

**Create:**

```
POST /v1/expense/expenses?format=fields&organizationId={id}&expenseType=ReceiptVerification
```

**Update:**

```
PUT /v1/expense/expenses/{expenseId}?format=fields
```

Send the full fields payload as the request body in both cases.

### Using standard JSON format

Alternatively, extract values from the fields and use the standard expense format:

````bash bash theme={"system"}
curl -X POST "https://stage-api.findity.com/api/v1/expense/expenses" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "organizationId": "ff808181963979e20196397a2098004b",
    "categoryId": "a1b2c3d4e5f6",
    "verification": {
      "type": "ReceiptVerification",
      "purchaseDate": "2024-03-15T00:00:00Z",
      "amount": 350.00,
      "taxAmount": 70.00,
      "currency": "SEK",
      "paymentTypeId": "a7384ac0d3dc45bf9d15f8de343cf612",
      "comment": "Office supplies for Q1 planning",
      "receiptAttachment": {
        "id": "ff808181826e28b201826e56fc980005"
      }
    }
  }'
``

### Example response

```json
{
  "id": "8a2b4c6d8e0f1a2b3c4d5e6f7a8b9c0d",
  "organizationId": "ff808181963979e20196397a2098004b",
  "personId": "ff808181963979e20196397a119f002d",
  "status": "NORMAL",
  "processStatus": "DRAFT",
  "categoryId": "a1b2c3d4e5f6",
  "reimbursementCurrency": "SEK",
  "reimbursementAmount": 350.00,
  "dateCreated": "2024-03-15T10:30:00Z",
  "lastUpdated": "2024-03-15T10:30:00Z",
  "verification": {
    "type": "ReceiptVerification",
    "purchaseDate": "2024-03-15T00:00:00Z",
    "amount": 350.00,
    "taxAmount": 70.00,
    "currency": "SEK",
    "paymentTypeId": "a7384ac0d3dc45bf9d15f8de343cf612",
    "comment": "Office supplies for Q1 planning",
    "receiptAttachment": {
      "id": "ff808181826e28b201826e56fc980005"
    }
  },
  "meta": {
    "abbreviation": {
      "reimbursementDescription": "350.00 SEK",
      "dateDescription": "15 Mar 2024"
    },
    "capabilities": {
      "canBeEdited": true,
      "canBeDeleted": true,
      "canBeSentIn": true,
      "canBeMerged": false
    }
  }
}
````

## Receipt attachments

The `verification.receiptAttachment` field uses the `CONTENT_HOLDER` control type. It stores the content ID from the upload step.

### Uploading additional attachments

Some expenses support multiple attachments. Upload each file separately and reference the IDs:

```bash bash theme={"system"}
curl -X POST "https://stage-api.findity.com/api/v1/expense/content?organizationId={orgId}" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/pdf" \
  -H "Content-Name: invoice.pdf" \
  --data-binary @invoice.pdf
```

### Retrieving receipt images

Fetch receipt images at a specific size for display in your UI:

```
GET /v1/expense/content/{id}/image?size=400x400
```

The API resizes the image to fit within the specified dimensions while preserving aspect ratio.

### Supported file types

| Type | Content-Type | Notes |
| - | - | - |
| JPEG | `image/jpeg` | Most common for phone camera receipts |
| PNG | `image/png` | Screenshots and scanned documents |
| PDF | `application/pdf` | Invoices and formal documents |

> [!WARNING]
>
> The maximum file size is controlled by the organization's `expenseReceiptMaxSize` setting (in MB). Check this value from the organization's `settings` object to validate file size client-side before uploading.

## Card transaction expenses

When an organization has card integrations, card transactions can be automatically converted into receipt expenses. These appear as draft expenses with the card transaction data pre-filled.

Card transaction expenses include:

* Pre-filled amount, currency, and date from the transaction
* A reference to the card transaction ID
* `meta.capabilities.canBeMerged: true` if the expense can be merged with a manually created expense

The user reviews the pre-filled data, attaches a receipt, selects a category, and submits — the same fields flow as a regular receipt expense.

## Common integration patterns

> **Scan-first expense creation**
>
> The recommended flow for receipt expenses is scan-first: upload the receipt with `action=scan`, then initialize fields with GET and apply the scan result via PUT. This pre-fills amount, tax, currency, date, and suggests categories — reducing manual entry to selecting the correct category and confirming values.
>
> ```
> POST /v1/expense/content?action=scan&organizationId={id}
> → Extract scanResult.id and content id
> GET /v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/fields
> → Initial field structure
> PUT /v1/expense/me/organizations/{id}/expensetypes/ReceiptVerification/fields?applyScanResult={scanResultId}
> → Fields pre-filled with OCR data
> ```

> **Handling foreign currency expenses**
>
> When the user selects a currency different from the organization's reimbursement currency, the exchange rate and reimbursement amount fields appear automatically after the `requiresUpdate` round-trip. Display the reimbursement amount prominently so the user knows the final amount they'll receive. The exchange rate is pre-filled from Findity's rate service but can be manually overridden if the organization allows it.

> **Email-based expense creation**
>
> Organizations can configure an expense email address (available in the organization's `settings.expenseEmail`). Receipts forwarded to this email are automatically created as draft expenses with OCR scanning applied. These appear in the user's draft list with the receipt already attached and data pre-filled.

> **Rendering the receipt alongside the form**
>
> Display the receipt image next to the expense form so users can reference it while filling in details. Fetch the image using the content ID from the `verification.receiptAttachment` field:
>
> ```
> GET /v1/expense/content/{contentId}/image?size=600x800
> ```
>
> On mobile, show the receipt as a tappable thumbnail that opens a full-screen viewer.

> **Handling rejected expenses**
>
> When a receipt expense is rejected, load it with the fields endpoint using `expenseRecordId`. The response includes an `INFORMATION` field with `informationType: error` containing the approver's rejection comment. Display this prominently at the top of the form so the user knows what to fix before resubmitting.

## Error handling

Common errors when working with receipt expenses:

| Status code | Error code | Description |
| - | - | - |
| `400` | `INVALID_JSON_BODY` | Failed to parse the request body. Verify your JSON payload. |
| `400` | `INVALID_JSON_PROPERTY_VALUE` | Missing or invalid `type` on verification — ensure `type` is set to `ReceiptVerification`. |
| `400` | `NOT_A_RECEIPT_VERIFICATION_CATEGORY` | The category ID is not valid for receipt expenses. Fetch categories for `ReceiptVerification`. |
| `400` | `CONTENT_NOT_FOUND` | The referenced content ID does not exist. Verify the receipt was uploaded successfully. |
| `400` | `CONTENT_TOO_BIG` | The uploaded file exceeds the max size. |
| `400` | `TOTAL_AMOUNT_REQUIRED` | Total amount is missing. Ensure `verification.totalAmount` has a value. |
| `404` | `EXPENSE_RECORD_NOT_FOUND` | The expense ID does not exist or is not accessible by the current user. |
| `404` | `CATEGORY_NOT_FOUND` | The specified category does not exist in the organization. |

## Next steps

> **[Fields reference](/docs/fields)**
>
> Full reference for the Fields system, control types, and the update cycle

> **[Content API](/reference/create-content)**
>
> API reference for uploading receipts and attachments

> **[Mileage expenses](/docs/fields-milage-expenses)**
>
> Guide for creating distance-based mileage expenses using Fields

> **[Per diem expenses](/docs/fields-per-diem-expenses)**
>
> Guide for creating per diem / subsistence allowance expenses
