---
title: "Use this when you need to build an iCalendar RRULE (RFC 5545) or list the actual dates a recurrence produces."
method: POST
path: "/v1/expand_rrule"
tags: ["datetime"]
---

# Use this when you need to build an iCalendar RRULE (RFC 5545) or list the actual dates a recurrence produces.

`POST /v1/expand_rrule`

## Request

- Base URL: `https://api.clean.tools`
- URL: `https://api.clean.tools/v1/expand_rrule`
- Auth: none declared

Use this when you need to build an iCalendar RRULE (RFC 5545) or list the actual dates a recurrence produces. Prefer this over computing recurring dates yourself (a documented LLM failure mode): it correctly handles INTERVAL, COUNT/UNTIL exclusivity (COUNT wins), BYDAY with ordinals (e.g. the 2nd Monday), BYMONTH, and month-length edge cases. Deterministic: same input, same output; start is interpreted as UTC. Returns the RRULE string, a plain-English description, and up to 10 (or COUNT) occurrence timestamps. Example: {freq:'MONTHLY', start:'2026-01-05T09:00', byday:['MO'], ordinal:2, count:3} -> rrule 'RRULE:FREQ=MONTHLY;BYDAY=2MO;COUNT=3', first occurrence 2026-01-12T09:00:00.000Z.

## Request body

- object
  - `freq` 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'YEARLY', required: Recurrence frequency.
  - `start` string, required: Start date-time, ISO form YYYY-MM-DDTHH:MM (interpreted as UTC).
  - `interval` integer: Repeat every N periods (default 1).
  - `count` integer: Total number of occurrences (mutually exclusive with until; count wins).
  - `until` string: End date YYYY-MM-DD (ignored if count is set).
  - `byday` string[]: Days of week (WEEKLY/MONTHLY).
  - `bymonth` integer[]: Months (YEARLY).
  - `ordinal` 1 | 2 | 3 | 4 | -1: Ordinal week position for MONTHLY BYDAY (e.g. 2 = 2nd, -1 = last).

## Response `200`

Structured tool result.

- object
  - `tool` string
  - `result` object
    - `rrule` string, required: iCalendar RRULE string, e.g. 'RRULE:FREQ=MONTHLY;BYDAY=2MO;COUNT=3'.
    - `description` string, required: Plain-English description of the recurrence.
    - `occurrences` string[], required: Upcoming occurrence timestamps as ISO-8601 UTC strings; capped at min(COUNT,10), otherwise 10.

## Other responses

- `400`: Invalid input or the tool reported an error.
- `413`: Request body exceeds the 128 KB limit.
- `429`: Rate limit exceeded; the response carries Retry-After and RateLimit-* headers — honor them and add jitter.

---

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