# Recursive AI — Booking API

Book a meeting with Recursive AI over plain HTTPS + JSON. The booking page at
recursiveai.org/book uses the same API. Machine-readable spec:
[`openapi.json`](openapi.json).

Base URL: `https://recursiveai.org/book/api`

## Flow

1. `GET /get-options` — check `status` is `available`. Read `durations` and `topics`.
2. `GET /get-availability?duration=30&timeZone=Europe/Berlin` — pick a slot. Optional
   `from` / `to` dates (YYYY-MM-DD, in `timeZone`).
3. `POST /create-booking` — send the slot's exact `start`. Keep the returned `token`.
4. Later, with the token: `POST /get-booking`, `POST /reschedule-booking`,
   `POST /cancel-booking`, `GET /get-booking-ics?token=…`.

```bash
curl -s 'https://recursiveai.org/book/api/get-availability?duration=30&timeZone=Europe/Berlin'

curl -s -X POST https://recursiveai.org/book/api/create-booking \
  -H 'Content-Type: application/json' \
  -d '{"start":"2026-10-14T14:00:00Z","duration":30,"topic":"project",
       "name":"Ada Lovelace","email":"ada@example.com","company":"Analytical Engines",
       "note":"Curious how Alera handles agent tool routing.","timeZone":"Europe/Berlin"}'
```

## Rules

- **Times.** `start`/`end` are UTC; `startLocal`/`endLocal` use the `timeZone` you
  pass. Send back a slot `start` unchanged. Anything not currently offered gets
  `409 slot_unavailable`.
- **Topics.** `project`, `fractional-cto`, `something-else` (check `get-options`).
- **Durations.** 30 or 60 minutes (check `get-options`).
- **Fields.** `name`, `email`, `note` required; `company` optional. Length limits are in `get-options.fields`.
- **The token is the key.** 43 URL-safe chars. Anyone holding it can view, reschedule or
  cancel. We store only a hash of it and can't recover it. It's also in the
  confirmation email's links.
- **Emails.** Every booking sends a confirmation, reminders, and reschedule and cancel
  notices to the booker's address, with partners@recursiveai.org BCC'd.
- **Calendars.** Each confirmed booking has a Google Meet link (`meetUrl`), a `.ics` link,
  and an add-to-Google-Calendar link.
- **Limits.** A few booking attempts per IP per hour and per email per day, and at most 2
  upcoming meetings per email. Over the limit returns `429 rate_limited` or
  `409 too_many_active_bookings`.
- **Unavailable.** When the calendar backend is down or not configured, booking endpoints
  return `503 booking_unavailable`. Nothing is booked. Email partners@recursiveai.org instead.

## Errors

```json
{"error": "That time is no longer available. Please pick another slot.", "code": "slot_unavailable"}
```

| HTTP | code | meaning |
|---|---|---|
| 400 | `invalid_request` | a field is missing or invalid (message says which) |
| 404 | `not_found` | unknown token |
| 405 | `method_not_allowed` | use POST |
| 409 | `slot_unavailable` | not offered / just taken |
| 409 | `too_many_active_bookings`, `booking_cancelled`, `booking_pending`, `too_late`, `reschedule_limit` | state doesn't allow it |
| 429 | `rate_limited` | slow down |
| 503 | `booking_unavailable` | try later or email |
