---
title: "Recurring schedule reference"
description: "Complete reference for the schedule object: every frequency, field combination and curl example."
canonical_url: "https://getfiga.com/help/developers/api-schedule/"
---

# Recurring schedule reference

Adding a `schedule` object to the expense creation payload turns a one-time expense into a recurring template. The engine generates virtual instances automatically for each month view.

[← Back to API reference](https://getfiga.com/help/developers/api)

## Schedule object fields

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `frequency` | string | None | **Required.** One of: `once`, `daily`, `weekly`, `monthly`, `quarterly`, `yearly`. |
| `startDate` | string \| integer | None | **Required.** ISO date (`"2026-03-01"`) or Unix seconds (`1740787200`). |
| `endDate` | string \| integer | none | Hard end date. Cannot be combined with `endAfter`. |
| `dayOfMonth` | integer | none | Day of month (1–31). Used with `monthly` / `quarterly`, or paired with `monthOfYear` for `yearly`. |
| `monthOfYear` | integer | none | Month 1–12. Only for `yearly`, together with `dayOfMonth`. |
| `dayOfWeek` | integer | none | Day of week (0 = Sunday … 6 = Saturday). Used with `weekly` or `monthly`+`weekOfMonth`. |
| `daysOfWeek` | integer\[\] | none | Multiple days (e.g. `[1, 3, 5]` = Mon/Wed/Fri). `weekly` only. |
| `weekOfMonth` | integer | none | Week number (1–5). Requires `dayOfWeek`. Used with `monthly` / `quarterly`. |
| `interval` | integer | `1` | Repeat every N periods (1–100). E.g. `2` with `weekly` = every 2 weeks. |
| `endAfter` | object | none | End condition. Cannot be combined with `endDate`. See below. |
| `timezone` | string | `"Europe/Warsaw"` | IANA timezone for occurrence calculation. |

### endAfter object

| type | value | Description |
| --- | --- | --- |
| `"count"` | integer (1–1000) | Stop after N total occurrences. |
| `"date"` | ISO date or Unix seconds | Stop on/after this date. |

**End conditions are mutually exclusive**

You can use `endDate` **or** `endAfter`, but **not both**. Omit both for an open-ended (infinite) recurring schedule.

## Required fields by frequency

| frequency | Required extras | Allowed optional | Forbidden |
| --- | --- | --- | --- |
| `once` | none | none | dayOfMonth, dayOfWeek, daysOfWeek, weekOfMonth, interval ≠ 1 |
| `daily` | none | interval | dayOfMonth, dayOfWeek, daysOfWeek, weekOfMonth |
| `weekly` | `dayOfWeek` or `daysOfWeek` | interval | dayOfMonth, weekOfMonth |
| `monthly` | `dayOfMonth` _or_ (`weekOfMonth` + `dayOfWeek`) | interval | daysOfWeek |
| `quarterly` | `dayOfMonth` _or_ (`weekOfMonth` + `dayOfWeek`) | interval | daysOfWeek |
| `yearly` | none (legacy startDate rule) | interval, monthOfYear + dayOfMonth | daysOfWeek |

**weekOfMonth always requires dayOfWeek**

To express patterns like “first Monday” or “third Friday”, you must provide **both** `weekOfMonth` and `dayOfWeek`.

## frequency: once

A single scheduled occurrence at `startDate`. Useful for a future-dated expense that should appear on its due date.

```
curl -X POST https://api.figa.cc/api/v1/expenses \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Annual insurance premium",
    "amount": 240000,
    "categoryInput": "Insurance",
    "schedule": {
      "frequency": "once",
      "startDate": "2026-06-15"
    }
  }'
```

## frequency: daily

### Every day

```
"schedule": {
  "frequency": "daily",
  "startDate": "2026-03-01"
}
```

### Every 3 days

```
"schedule": {
  "frequency": "daily",
  "startDate": "2026-03-01",
  "interval": 3
}
```

### Every day for 30 days

```
"schedule": {
  "frequency": "daily",
  "startDate": "2026-03-01",
  "endAfter": { "type": "count", "value": 30 }
}
```

### Every day until end of year

```
"schedule": {
  "frequency": "daily",
  "startDate": "2026-03-01",
  "endDate": "2026-12-31"
}
```

## frequency: weekly

### Every Friday

```
"schedule": {
  "frequency": "weekly",
  "startDate": "2026-03-06",
  "dayOfWeek": 5
}
```

**dayOfWeek values**

`0` = Sunday, `1` = Monday, `2` = Tuesday, `3` = Wednesday, `4` = Thursday, `5` = Friday, `6` = Saturday.

### Every other Monday

```
"schedule": {
  "frequency": "weekly",
  "startDate": "2026-03-02",
  "dayOfWeek": 1,
  "interval": 2
}
```

### Monday, Wednesday, Friday every week

```
"schedule": {
  "frequency": "weekly",
  "startDate": "2026-03-02",
  "daysOfWeek": [1, 3, 5]
}
```

### Tuesday and Thursday, every 2 weeks, 20 occurrences

```
"schedule": {
  "frequency": "weekly",
  "startDate": "2026-03-03",
  "daysOfWeek": [2, 4],
  "interval": 2,
  "endAfter": { "type": "count", "value": 20 }
}
```

### Full curl: weekly team lunch

```
curl -X POST https://api.figa.cc/api/v1/expenses \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Team lunch",
    "amount": 15000,
    "categoryInput": "Food",
    "recipientInput": "Pizza Place",
    "schedule": {
      "frequency": "weekly",
      "startDate": "2026-03-06",
      "dayOfWeek": 5
    }
  }'
```

## frequency: monthly

### 1st of every month (rent, subscriptions)

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-01",
  "dayOfMonth": 1
}
```

### 15th of every month

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-15",
  "dayOfMonth": 15
}
```

### Last day of month (dayOfMonth: 31)

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-31",
  "dayOfMonth": 31
}
```

**dayOfMonth: 31 in short months**

When `dayOfMonth` exceeds the number of days in a month (e.g. 31 in February), the occurrence is placed on the last day of that month.

### Every other month on the 10th

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-10",
  "dayOfMonth": 10,
  "interval": 2
}
```

### First Monday of every month

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-06",
  "weekOfMonth": 1,
  "dayOfWeek": 1
}
```

### Third Friday of every month

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-16",
  "weekOfMonth": 3,
  "dayOfWeek": 5
}
```

### 12 monthly installments (loan repayment)

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-01",
  "dayOfMonth": 1,
  "endAfter": { "type": "count", "value": 12 }
}
```

### Monthly until December 2027

```
"schedule": {
  "frequency": "monthly",
  "startDate": "2026-01-01",
  "dayOfMonth": 1,
  "endDate": "2027-12-31"
}
```

### Full curl: monthly rent

```
curl -X POST https://api.figa.cc/api/v1/expenses \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Office rent",
    "amount": 420000,
    "categoryInput": "Housing",
    "recipientInput": "WeWork",
    "description": "Monthly office lease",
    "currency": "PLN",
    "schedule": {
      "frequency": "monthly",
      "startDate": "2026-01-01",
      "dayOfMonth": 1
    }
  }'
```

### Full curl: 36 installments (phone lease)

```
curl -X POST https://api.figa.cc/api/v1/expenses \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "iPhone lease",
    "amount": 12500,
    "categoryInput": "Equipment",
    "recipientInput": "Apple",
    "schedule": {
      "frequency": "monthly",
      "startDate": "2026-02-15",
      "dayOfMonth": 15,
      "endAfter": { "type": "count", "value": 36 }
    }
  }'
```

## frequency: quarterly

### 1st of each quarter

```
"schedule": {
  "frequency": "quarterly",
  "startDate": "2026-01-01",
  "dayOfMonth": 1
}
```

### 15th of each quarter

```
"schedule": {
  "frequency": "quarterly",
  "startDate": "2026-01-15",
  "dayOfMonth": 15
}
```

### First Monday of each quarter

```
"schedule": {
  "frequency": "quarterly",
  "startDate": "2026-01-05",
  "weekOfMonth": 1,
  "dayOfWeek": 1
}
```

### Full curl: quarterly tax advance

```
curl -X POST https://api.figa.cc/api/v1/expenses \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "VAT advance payment",
    "amount": 850000,
    "categoryInput": "Tax",
    "recipientInput": "Urząd Skarbowy",
    "schedule": {
      "frequency": "quarterly",
      "startDate": "2026-01-25",
      "dayOfMonth": 25
    }
  }'
```

## frequency: yearly

### Yearly on start date anniversary

```
"schedule": {
  "frequency": "yearly",
  "startDate": "2026-06-15"
}
```

Without `monthOfYear`, the yearly month and day come from `startDate`; a legacy `dayOfMonth` alone remains ignored. With `monthOfYear` (1–12), `dayOfMonth` (1–31) is required and defines the yearly date. The start still determines the interval phase and earliest generated term. The pair is available through the same schedule schema in the session API, API-key API and existing MCP schedule edits.

### Every 2 years

```
"schedule": {
  "frequency": "yearly",
  "startDate": "2026-06-15",
  "interval": 2
}
```

### Preserve February 29 after extending history

```
{
  "frequency": "yearly",
  "startDate": "2023-03-01",
  "monthOfYear": 2,
  "dayOfMonth": 29
}
```

This produces March 1 in 2023 and February 29 in 2024 and 2028. February 29 overflows to March 1 in non-leap years, preserving the existing yearly rule. A range backfill from a legacy February 29 anchor records this pair automatically. Reading an old schedule does not activate previously ignored fields.

### Full curl: yearly domain renewal

```
curl -X POST https://api.figa.cc/api/v1/expenses \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "figa.io domain renewal",
    "amount": 4500,
    "categoryInput": "Infrastructure",
    "recipientInput": "Cloudflare",
    "currency": "USD",
    "schedule": {
      "frequency": "yearly",
      "startDate": "2026-09-12"
    }
  }'
```

## Managing recurring expenses

To change fixed/variable monthly billing from an occurrence, use [`recurringSettings`](https://getfiga.com/help/developers/api#recurring-billing-settings). Save calendar changes separately. Schedule changes are unavailable for series with billing-method history.

### Read schedule details

```
curl -X GET https://api.figa.cc/api/v1/expenses/{expenseId} \
  -H "x-api-key: et_live_abc123..."
```

Returns the full expense object with `schedule`, `occurrences` array, and `stats` (totalOccurrences, paidOccurrences, progress, etc.).

### Read a single occurrence

```
curl -X GET "https://api.figa.cc/api/v1/expenses/{expenseId}?occurrence=1740787200" \
  -H "x-api-key: et_live_abc123..."
```

Pass the occurrence's scheduled Unix timestamp to get that specific instance.

### Change schedule for entire series

```
curl -X PUT https://api.figa.cc/api/v1/expenses/{expenseId} \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "schedule": {
      "frequency": "monthly",
      "startDate": "2026-01-05",
      "dayOfMonth": 5
    },
    "editScope": "ALL_INSTANCES"
  }'
```

### Update amount for this + future occurrences

```
curl -X PUT https://api.figa.cc/api/v1/expenses/{expenseId} \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 450000,
    "editScope": "FUTURE_INSTANCES"
  }'
```

### Override a single occurrence

```
curl -X PUT https://api.figa.cc/api/v1/expenses/{expenseId} \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 500000,
    "description": "Increased rent for March",
    "editScope": "THIS_INSTANCE"
  }'
```

### Skip an occurrence

`scheduledDate` accepts Unix seconds or ISO date `YYYY-MM-DD`.

#### Using Unix timestamp

```
curl -X POST https://api.figa.cc/api/v1/expenses/{expenseId}/skip/toggle \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"scheduledDate": 1740787200}'
```

#### Using ISO date (recommended)

```
curl -X POST https://api.figa.cc/api/v1/expenses/{expenseId}/skip/toggle \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"scheduledDate": "2026-03-30"}'
```

Call again with the same `scheduledDate` to restore a skipped occurrence. Only unpaid instances can be skipped. If occurrence is not found, API returns `404`.

### Convert recurring to one-time

```
curl -X PUT https://api.figa.cc/api/v1/expenses/{expenseId} \
  -H "x-api-key: et_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "schedule": null,
    "editScope": "ALL_INSTANCES"
  }'
```

### Delete single occurrence

```
curl -X DELETE "https://api.figa.cc/api/v1/expenses/{expenseId}?editScope=THIS_INSTANCE" \
  -H "x-api-key: et_live_abc123..."
```

### Delete entire series

```
curl -X DELETE "https://api.figa.cc/api/v1/expenses/{expenseId}?editScope=ALL_INSTANCES" \
  -H "x-api-key: et_live_abc123..."
```

## editScope reference

When updating (`PUT`) or deleting (`DELETE`) a recurring expense, `editScope` determines which occurrences are affected:

| Value | PUT effect | DELETE effect |
| --- | --- | --- |
| `THIS_INSTANCE` | Materializes and overrides only this occurrence. | Removes only this occurrence. |
| `FUTURE_INSTANCES` | Applies changes to this and all future occurrences. | Removes this and all future occurrences. |
| `ALL_INSTANCES` | Updates the template (all past + future). | Deletes the entire recurring series. |

**editScope is for recurring expenses only**

For one-time expenses, omit `editScope`. It is ignored for non-recurring expenses.

## Quick reference: common patterns

| Use case | schedule JSON |
| --- | --- |
| Monthly rent on 1st | `{ "frequency": "monthly", "startDate": "2026-01-01", "dayOfMonth": 1 }` |
| Weekly Friday coffee | `{ "frequency": "weekly", "startDate": "2026-01-02", "dayOfWeek": 5 }` |
| Quarterly tax (25th) | `{ "frequency": "quarterly", "startDate": "2026-01-25", "dayOfMonth": 25 }` |
| Yearly renewal | `{ "frequency": "yearly", "startDate": "2026-09-12" }` |
| Bi-weekly Mon payroll | `{ "frequency": "weekly", "startDate": "2026-01-05", "dayOfWeek": 1, "interval": 2 }` |
| Mon/Wed/Fri gym | `{ "frequency": "weekly", "startDate": "2026-01-05", "daysOfWeek": [1, 3, 5] }` |
| 1st Monday of month | `{ "frequency": "monthly", "startDate": "2026-01-05", "weekOfMonth": 1, "dayOfWeek": 1 }` |
| 12 installments | `{ "frequency": "monthly", "startDate": "2026-01-01", "dayOfMonth": 1, "endAfter": { "type": "count", "value": 12 } }` |
| Daily until end of year | `{ "frequency": "daily", "startDate": "2026-01-01", "endDate": "2026-12-31" }` |
| Every 3 days, 30 times | `{ "frequency": "daily", "startDate": "2026-01-01", "interval": 3, "endAfter": { "type": "count", "value": 30 } }` |
