# Free Tools API (No Key)

Two no-key endpoints from nowgetitdone.com/tools: natural language to a due date and RRULE, and an RRULE explained in plain English with its next dates.

The free tools at [nowgetitdone.com/tools](https://nowgetitdone.com/tools) also answer over HTTP. No account, no API key: send a GET request and read JSON back. They are separate from the [REST API](/docs/api), which needs a `gid_` key and works with your tasks; these work only with the text you send.

Both endpoints run the same code as the tool pages, and the date parser is the one the GetItDone task box runs as you type ([Quick Add](/docs/quick-add) lists everything it reads).

## The contract

- **No authentication.** CORS is open (`Access-Control-Allow-Origin: *`), so a browser on any origin can call them.
- **JSON by default.** Send `Accept: text/markdown` for the same result as Markdown.
- **Errors are RFC 9457** `application/problem+json`, with the reason in `detail`.
- **Rate limit:** 30 requests a minute and 300 a day per IP address, across both endpoints. Over the limit you get `429` with a `Retry-After` header in seconds.
- **No caching:** results depend on "today" in the timezone you pass, so every response is `Cache-Control: no-store`.
- Every response names its docs in an `X-Tool-Docs` header.
- OpenAPI 3.1: [nowgetitdone.com/tools/openapi.json](https://nowgetitdone.com/tools/openapi.json).

## Parse a date from text

`GET https://nowgetitdone.com/api/tools/parse-date?text=…&tz=…`

| Parameter | Required | Meaning                                                                                           |
| --------- | -------- | ------------------------------------------------------------------------------------------------- |
| `text`    | yes      | The task as you would type it, up to 500 characters.                                              |
| `tz`      | no       | IANA timezone that "today" and "tomorrow" are counted in, such as `America/Toronto`. Default UTC. |

```bash
curl 'https://nowgetitdone.com/api/tools/parse-date?text=review%20the%20report%20every%20friday&tz=America/Toronto'
```

The response carries:

- `strippedTitle`: the text with every recognised phrase removed, which is the task title.
- `dueDate` and `startDate`: `YYYY-MM-DD` or `null`. A date the text does not state is never invented.
- `rrule`: the RFC 5545 rule for a repeat phrase, or `null`. `recurrence` has the same rule in plain English, its first day and the next five dates.
- `timeOfDay`: a clock time such as "at 3pm" that was read but is not stored, with `saved: false`. GetItDone schedules whole days.
- `today` and `tz`: the day and zone the relative words were read in.
- `explanation`: one plain-English line covering all of the above.

## Explain an RRULE

`GET https://nowgetitdone.com/api/tools/rrule-explainer?rrule=…&tz=…`

| Parameter | Required | Meaning                                                                                                        |
| --------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `rrule`   | yes      | An RRULE value, with or without the `RRULE:` prefix, optionally after a `DTSTART` line. Up to 1000 characters. |
| `tz`      | no       | IANA timezone "today" is read in when there is no `DTSTART;TZID=…`. Default UTC.                               |

```bash
curl 'https://nowgetitdone.com/api/tools/rrule-explainer?rrule=FREQ%3DWEEKLY%3BINTERVAL%3D2%3BBYDAY%3DTU'
```

The response has the rule normalised (`rrule`), in plain English (`description`), its first day (`startDate`), the next 10 dates (`nextDates`) and `notes` wherever GetItDone's reading and a strict RFC 5545 reading differ.

It reads DAILY, WEEKLY and MONTHLY rules with `INTERVAL`, plain `BYDAY` weekdays, one `BYMONTHDAY`, `UNTIL` or `COUNT`, and `WKST`. Anything else, such as `FREQ=YEARLY`, `BYSETPOS` or a numbered `BYDAY=1MO`, is a `400` that names the part, so you never get dates for a rule that was only half read.

## Errors

```json
{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "BYSETPOS is not supported: GetItDone rules repeat daily, on chosen weekdays, or on one day of the month."
}
```

| Status | When                                                                  |
| ------ | --------------------------------------------------------------------- |
| `400`  | A required parameter is missing, too long, or cannot be read.         |
| `429`  | Over the per-address limit. Wait for `Retry-After` seconds and retry. |
