---
title: "Create an expense"
method: POST
path: "/v1/expenses"
tags: ["Expenses"]
---

# Create an expense

`POST /v1/expenses`

## Request

- Base URL: `https://api.frihet.io`
- URL: `https://api.frihet.io/v1/expenses`
- Auth: API key in header `X-API-Key`

Record a new business expense.

## Request body

- ExpenseCreate
  - `description` string, required: Expense description
  - `amount` number, required: Expense amount
  - `date` string, date: Expense date in ISO format
  - `paidDate` string, date, nullable: Effective payment date (fecha de pago, YYYY-MM-DD). Drives cash-basis period assignment for Modelos 111/115/130. When absent: under accrual (devengo) criteria the expense `date` is used; under the opt-in Modelo 130 cash-basis criterion (criterio de cobros y pagos) an absent paidDate means not yet paid and the expense is excluded until paid. On PATCH, an explicit null clears the field.
  - `category` string: Expense category
  - `vendor` string: Vendor or supplier name
  - `taxDeductible` boolean: Whether the expense is tax deductible
  - `currency` string: ISO 4217 transaction currency. Defaults to EUR.
  - `exchangeRate` number: Exchange rate used to convert amount into functionalCurrency.
  - `exchangeRateSource` string: Source/provider of the exchange rate snapshot.
  - `exchangeRateDate` string, date: Exchange rate date (YYYY-MM-DD).
  - `functionalCurrency` string: Workspace/reporting currency. Defaults to EUR.
  - `functionalAmount` number: Amount converted into functionalCurrency.
  - `attachments` FileAttachment[]
    - `fileId` string, required: Opaque uploaded file reference. Not a path or URL.
    - `originalName` string, required: Filename only; local paths are rejected.
    - `contentType` 'application/pdf' | 'image/jpeg' | 'image/jpg' | 'image/png' | 'image/webp' | 'image/heic' | 'image/heif' | 'image/tiff', required
    - `size` integer, required
    - `checksumSha256` string
  - `recurring` ExpenseRecurringConfig: Recurring expense configuration. Set on a template expense to auto-generate copies on schedule.
    - `enabled` boolean, required: Whether recurring generation is active
    - `frequency` 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly', required: How often to generate a new expense
    - `nextDate` string, date, required: Next scheduled generation date (ISO YYYY-MM-DD)
    - `endDate` string, date: Stop generating after this date (optional)
    - `maxOccurrences` integer: Maximum number of expenses to generate (optional)
    - `occurrencesGenerated` integer: Number of expenses generated so far (server-managed, read-only)

## Response `201`

Expense created

- Expense
  - `id` string: Unique identifier
  - `createdAt` string, date-time
  - `updatedAt` string, date-time
  - `description` string, required: Expense description
  - `amount` number, required: Expense amount
  - `date` string, date: Expense date in ISO format
  - `paidDate` string, date, nullable: Effective payment date (fecha de pago, YYYY-MM-DD). Drives cash-basis period assignment for Modelos 111/115/130. When absent: under accrual (devengo) criteria the expense `date` is used; under the opt-in Modelo 130 cash-basis criterion (criterio de cobros y pagos) an absent paidDate means not yet paid and the expense is excluded until paid. On PATCH, an explicit null clears the field.
  - `category` string: Expense category
  - `vendor` string: Vendor or supplier name
  - `taxDeductible` boolean: Whether the expense is tax deductible
  - `currency` string: ISO 4217 transaction currency. Defaults to EUR.
  - `exchangeRate` number: Exchange rate used to convert amount into functionalCurrency.
  - `exchangeRateSource` string: Source/provider of the exchange rate snapshot.
  - `exchangeRateDate` string, date: Exchange rate date (YYYY-MM-DD).
  - `functionalCurrency` string: Workspace/reporting currency. Defaults to EUR.
  - `functionalAmount` number: Amount converted into functionalCurrency.
  - `attachments` FileAttachment[]
    - `fileId` string, required: Opaque uploaded file reference. Not a path or URL.
    - `originalName` string, required: Filename only; local paths are rejected.
    - `contentType` 'application/pdf' | 'image/jpeg' | 'image/jpg' | 'image/png' | 'image/webp' | 'image/heic' | 'image/heif' | 'image/tiff', required
    - `size` integer, required
    - `checksumSha256` string
  - `recurring` ExpenseRecurringConfig: Recurring expense configuration. Set on a template expense to auto-generate copies on schedule.
    - `enabled` boolean, required: Whether recurring generation is active
    - `frequency` 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly', required: How often to generate a new expense
    - `nextDate` string, date, required: Next scheduled generation date (ISO YYYY-MM-DD)
    - `endDate` string, date: Stop generating after this date (optional)
    - `maxOccurrences` integer: Maximum number of expenses to generate (optional)
    - `occurrencesGenerated` integer: Number of expenses generated so far (server-managed, read-only)

## Other responses

- `400`: Bad request - invalid parameters or request body
- `401`: Authentication required or invalid API key
- `429`: Rate limit exceeded (100 requests per minute)
- `500`: Internal server error

---

[API](https://skmtc.dev/frihet/apis/frihet-api.md) · [All operations](https://skmtc.dev/frihet/apis/frihet-api/llms.txt) · [OpenAPI document](https://skmtc.dev/frihet/apis/frihet-api/revisions/3dd37f6a72d1?raw)
