Recurrence Rules
Funding schedules and expenses both repeat, and monetr describes "repeats" with a recurrence rule. It's the ruleset
field on funding schedules and on expense spending objects, and it's the field most
likely to hand you a 400 the first time you try.
The format is RFC 5545, the same standard calendar invites use. monetr accepts a useful subset of it rather than the whole thing, and the rules it rejects aren't obvious, so this page is the short version of what actually works.
If you only want something that runs, skip to the cookbook. Every rule there is verified against monetr's validator.
The shape
A ruleset is two lines joined by a newline. In JSON that's an escaped \n, since it's one string:
DTSTART is when the pattern begins, in UTC, formatted YYYYMMDDTHHMMSSZ. RRULE is the pattern itself.
Three rules that will catch you
Whatever you get wrong, the response is "Ruleset must be valid". It doesn't say which part broke. So if a rule is
rejected, work through these three before anything else.
DTSTART is required. Most rrule libraries will happily hand you a bare RRULE: line, and monetr rejects it.
Without an explicit start the underlying library falls back to a zero time, and every date calculation downstream comes
out wrong, so monetr would rather you say when the schedule begins.
BYHOUR, BYMINUTE and BYSECOND are rejected. monetr works in whole days. Nothing in a budget cares what time of
day rent is due, and a rule that fires 3600 times a day is a good way to hang a forecast. If your library adds these
automatically, strip them.
The time in DTSTART should be midnight in your account's timezone, expressed as UTC. For America/Chicago that's
T060000Z in winter and T050000Z in summer, because the offset moves with daylight saving. This one won't fail
validation, but getting it wrong shifts every occurrence onto the wrong day. See Timestamps.
Cookbook
Every rule below is checked against monetr's validator. Change the DTSTART date to the first occurrence you actually
want, keeping the time at midnight in your timezone.
These are the same patterns the app's own funding schedule picker offers.
BYMONTHDAY=-1 counts backwards from the end of the month, so it lands on the 28th, 30th or 31st as appropriate. That's
how you say "last day of the month" without special-casing February.
Where rules are used
Funding schedules always need one. It's when you get paid.
Expenses always need one. It's when the thing comes due, and it's what empties the envelope and starts it filling again.
Goals never take one. A goal happens once, so sending a ruleset with "spendingType": "goal" is rejected with
"Ruleset cannot be specified for goals". Goals use nextRecurrence on its own for the target date.
The forecast endpoints take the same format under a different key, recurrenceRule. That inconsistency is
in the API, not in these docs.
The rule and the next date are separate
Both funding schedules and spending objects carry a ruleset and a nextRecurrence, and they're not derived from
each other at write time. nextRecurrence is the actual next occurrence, and the rule is what generates the one after
that.
So you can have a rule that says "the 1st of every month" and a nextRecurrence of the 15th, if that's genuinely when
the next one falls. monetr will use the 15th, then go back to the 1st afterwards. Useful when you're setting up
mid-cycle, and confusing if you assumed the rule alone decided everything.
The two endpoints differ in how forgiving they are about nextRecurrence:
- Funding schedules will work it out from the rule if you leave it off or send something in the past.
- Spending objects reject anything not in the future, and midnight today already counts as past.