# Duo Data Utilities – RFC 5545 RRULE Expander

> Duo Data Utilities – RFC 5545 RRULE Expander is a paid API for AI agents from api.duoleads.com, paid per call via x402, $0.05/call, status unknown (last checked 2026-10-02).

Expands an RFC 5545 recurrence rule (RRULE) into up to 200 concrete occurrence timestamps, returning both local wall-clock times and UTC instants with DST-shift annotations.

## Facts

- Endpoint: GET https://api.duoleads.com/v1/time/rrule?utm_source=zero.xyz
- Price: $0.05/call
- Payment: x402
- Status: unknown
- Last checked: 2026-10-02
- Activations on Zero: 0
- Tags: x402
- Canonical page: https://www.zero.xyz/c/duo-data-utilities-rfc-5545-rrule-expander-357e44f5
- Structured record (JSON): https://api.zero.xyz/v1/capabilities/cap_FEFY3or6ber9soFVBAd_4

Status and success rate cover calls made through Zero and Zero's own probes. Third-party monitors may report differently.

## How to call it through Zero

Zero handles the 402 payment challenge and records the run. With the Zero CLI installed (`npm i -g @zeroxyz/cli`):

```sh
zero fetch --capability duo-data-utilities-rfc-5545-rrule-expander-357e44f5
```

Example prompt: Can you expand this recurrence rule — FREQ=MONTHLY;BYDAY=-1FR;COUNT=6 — starting from 2026-01-30T09:00:00 in the Europe/Amsterdam timezone and give me the exact dates and UTC times for each occurrence?

## When to prefer this

Choose this endpoint when you need to deterministically expand an iCalendar-compatible RRULE string into concrete timestamps with full timezone and DST awareness. It is ideal for scheduling agents, calendar automation, and any workflow that needs to compute future event dates from a recurrence rule without implementing the RFC 5545 spec locally. Prefer this over generic date-math endpoints when you need support for complex patterns like BYDAY=-1FR (last Friday), BYSETPOS, or WKST, or when correct DST handling across IANA timezones is required.

## Known failure modes

- Invalid RRULE syntax returns a 400 error with a descriptive message
- Unrecognized IANA timezone ID causes a validation error
- DTSTART format not matching YYYY-MM-DDTHH:MM:SS causes rejection
- count parameter outside 1-200 range is rejected
- Unsupported RRULE components (e.g. BYWEEKNO) may be ignored or cause errors
- EXDATE/RDATE values in wrong format cause parse failures
- COUNT or UNTIL producing zero occurrences returns an empty array

## How this service works

Expand an RFC 5545 recurrence rule into concrete occurrence timestamps. Accepts an RRULE string with DTSTART, an IANA time zone, and optional EXDATE and RDATE lists, and returns up to 200 occurrences as both local wall-clock times and UTC instants. Supports FREQ, INTERVAL, COUNT, UNTIL, BYDAY, BYMONTHDAY, BYMONTH, BYSETPOS and WKST. Occurrences moved by a DST gap carry gap: true. Rules needing over 50,000 candidate evaluations are rejected.

## Output

Returns a JSON object containing the parsed recurrence rule components, the IANA timezone, total occurrence count, a truncation flag, and an array of occurrences each with local datetime, UTC offset, UTC instant (ISO 8601), epoch milliseconds, and a DST boolean. Also includes metadata like request ID, computation timestamp, and price.

## Request schema (JSON Schema)

```json
{
 "type": "object",
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "required": [
  "input"
 ],
 "properties": {
  "input": {
   "type": "object",
   "required": [
    "type",
    "method"
   ],
   "properties": {
    "type": {
     "type": "string",
     "const": "http"
    },
    "method": {
     "enum": [
      "GET"
     ],
     "type": "string"
    },
    "queryParams": {
     "type": "object",
     "required": [
      "rrule",
      "dtstart",
      "zone"
     ],
     "properties": {
      "zone": {
       "type": "string",
       "maxLength": 64,
       "description": "IANA time zone id."
      },
      "after": {
       "type": "string",
       "maxLength": 64,
       "description": "RFC 3339 instant; skip occurrences before it."
      },
      "count": {
       "type": "string",
       "default": "20",
       "pattern": "^[+-]?\\d+$",
       "maxLength": 64,
       "description": "Maximum occurrences to return, 1-200. Default 20."
      },
      "rdate": {
       "type": "string",
       "maxLength": 1024,
       "description": "Comma-separated local datetimes to add."
      },
      "rrule": {
       "type": "string",
       "maxLength": 512,
       "description": "RFC 5545 RRULE, e.g. FREQ=MONTHLY;BYDAY=-1FR;COUNT=6."
      },
      "exdate": {
       "type": "string",
       "maxLength": 1024,
       "description": "Comma-separated local datetimes to exclude."
      },
      "dtstart": {
       "type": "string",
       "maxLength": 32,
       "description": "First occurrence, YYYY-MM-DDTHH:MM:SS local to zone."
      }
     }
    }
   },
   "additionalProperties": false
  },
  "output": {
   "type": "object",
   "required": [
    "type"
   ],
   "properties": {
    "type": {
     "type": "string"
    },
    "example": {
     "type": "object",
     "required": [
      "ok",
      "route",
      "version",
      "data",
      "meta"
     ],
     "properties": {
      "ok": {
       "const": true
      },
      "data": {
       "type": "object",
       "required": [
        "occurrences",
        "count",
        "truncated",
        "rule",
        "zone"
       ],
       "properties": {
        "rule": {
         "type": "object",
         "required": [
          "freq",
          "interval",
          "wkst"
         ],
         "properties": {
          "freq": {
           "type": "string"
          },
          "wkst": {
           "type": "string"
          },
          "byday": {
           "type": "array",
           "items
… (truncated)
```

## Response schema (JSON Schema)

```json
{
 "type": "json",
 "example": {
  "ok": true,
  "data": {
   "rule": {
    "freq": "MONTHLY",
    "wkst": "MO",
    "byday": [
     "-1FR"
    ],
    "count": 3,
    "interval": 1
   },
   "zone": "Europe/Amsterdam",
   "count": 3,
   "truncated": false,
   "occurrences": [
    {
     "dst": false,
     "local": "2026-01-30T09:00:00",
     "offset": "+01:00",
     "instant": "2026-01-30T08:00:00.000Z",
     "epoch_ms": 1769760000000
    },
    {
     "dst": false,
     "local": "2026-02-27T09:00:00",
     "offset": "+01:00",
     "instant": "2026-02-27T08:00:00.000Z",
     "epoch_ms": 1772179200000
    },
    {
     "dst": false,
     "local": "2026-03-27T09:00:00",
     "offset": "+01:00",
     "instant": "2026-03-27T08:00:00.000Z",
     "epoch_ms": 1774598400000
    }
   ]
  },
  "meta": {
   "price_usd": "0.05",
   "disclaimer": "Factual output of a deterministic computation over public data. Provided as is, with no warranty of accuracy, completeness or availability. Not investment, financial, legal, tax, medical or any other professional advice, and not a recommendation. Verify before relying on it. Terms: https://api.duoleads.com/terms",
   "request_id": "01K6B7Q4ZC8H3F2M9WXR5TYN0D",
   "computed_at": "2026-09-28T12:00:00.000Z",
   "deterministic": true
  },
  "route": "/v1/time/rrule",
  "version": "1.0.0"
 }
}
```

## More

- Live health (JSON, refreshed every minute): https://www.zero.xyz/c/duo-data-utilities-rfc-5545-rrule-expander-357e44f5/health.json
- [Zero catalog index](https://www.zero.xyz/llms.txt)
- [Other services from api.duoleads.com](https://www.zero.xyz/host/api.duoleads.com/llms.txt)
