Figa

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

Schedule object fields

Field Type Default Description
frequencystringRequired. One of: once, daily, weekly, monthly, quarterly, yearly.
startDatestring | integerRequired. ISO date ("2026-03-01") or Unix seconds (1740787200).
endDatestring | integernoneHard end date. Cannot be combined with endAfter.
dayOfMonthintegernoneDay of month (1–31). Used with monthly / quarterly.
dayOfWeekintegernoneDay of week (0 = Sunday … 6 = Saturday). Used with weekly or monthly+weekOfMonth.
daysOfWeekinteger[]noneMultiple days (e.g. [1, 3, 5] = Mon/Wed/Fri). weekly only.
weekOfMonthintegernoneWeek number (1–5). Requires dayOfWeek. Used with monthly / quarterly.
intervalinteger1Repeat every N periods (1–100). E.g. 2 with weekly = every 2 weeks.
endAfterobjectnoneEnd condition. Cannot be combined with endDate. See below.
timezonestring"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 secondsStop 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
oncenonenonedayOfMonth, dayOfWeek, daysOfWeek, weekOfMonth, interval ≠ 1
dailynoneintervaldayOfMonth, dayOfWeek, daysOfWeek, weekOfMonth
weeklydayOfWeek or daysOfWeekintervaldayOfMonth, weekOfMonth
monthlydayOfMonth or (weekOfMonth + dayOfWeek)intervaldaysOfWeek
quarterlydayOfMonth or (weekOfMonth + dayOfWeek)intervaldaysOfWeek
yearlynone (uses startDate)intervaldaysOfWeek

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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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"
}

For yearly, the recurrence date is derived from startDate. No additional fields (dayOfMonth, dayOfWeek) are required.

Every 2 years

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

Full curl — yearly domain renewal

curl -X POST https://app.figa.io/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

Read schedule details

curl -X GET https://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/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://app.figa.io/api/v1/expenses/{expenseId}?editScope=THIS_INSTANCE" \
  -H "x-api-key: et_live_abc123..."

Delete entire series

curl -X DELETE "https://app.figa.io/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_INSTANCEMaterializes and overrides only this occurrence.Removes only this occurrence.
FUTURE_INSTANCESApplies changes to this and all future occurrences.Removes this and all future occurrences.
ALL_INSTANCESUpdates 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 } }